Coding for KidsCoding for Kids
창의적인 레벨도전 과제교사 가이드
기능 투표
고급 파이썬 개발 과정
챕터
>
레벨

직렬화 모듈
구조체 모듈

목표

struct 모듈을 사용하여 새 농지의 최종 데이터 분해 작업을 설정하세요.

길 끝에는 이미 건설된 새 농지와 이미 심어진 농작물을 관리하는 서비스 스테이션이 있습니다. 여기에서는 이미 심어진 농작물의 데이터와 농지의 예상 산출량 데이터를 점검하고 처리할 것입니다. 이 장의 다른 레벨과 마찬가지로, 우리는 데이터를 직렬화(serializing)하고 역직렬화(deserializing)하는 작업을 진행하며, 마지막으로 struct 모듈을 소개할 것입니다.

struct 모듈은 데이터를 바이너리 형식으로 패킹하는 일련의 직렬화 함수를 제공합니다. 우리가 사용한 다른 모듈들과 달리, 직렬화 및 이후 역직렬화할 때 데이터의 구조를 세밀하게 제어할 수 있어 다른 모듈보다 더 유연합니다. 데이터를 처리하기 위해 사용할 다음 함수에 접근하려면 import struct 를 사용하세요:

  • struct.calcsize(): 주어진 형식 문자열이 몇 바이트로 패킹되는지 결정합니다. 이는 확인하려는 형식을 인수로 받아 처리합니다. 우리가 사용할 형식은 다음과 같습니다:
    • 정수: 'i' 로 표현되며, 정수 데이터를 위한 형식입니다.
    • 실수: 'f' 로 표현되며, 소수점 숫자 데이터를 위한 형식입니다.
    • 더블: 'd' 로 표현되며, 실수 형식으로는 부족한 고정밀 소수점 숫자 데이터를 위한 형식입니다.
  • struct.pack(): 원하는 형식으로 데이터를 직렬화하여 바이너리로 패킹합니다. 이 함수는 두 개 이상의 인수를 받을 수 있으며, 첫 번째 인수는 사용할 형식을, 그 이후의 인수는 직렬화할 값들입니다. 사용 가능한 형식은 앞서 설명한 것들이며, 추가하는 인수의 개수에 맞게 해당 형식을 반복해서 사용해야 합니다.
  • struct.unpack(): 패킹된 바이너리 데이터를 역직렬화합니다. 이 함수는 두 개의 인수를 받는데, 첫 번째는 데이터가 직렬화되었던 형식과 일치하는 형식이고, 두 번째는 직렬화된 데이터입니다.
  • struct.iter_unpack(): 패킹된 바이너리 데이터를 역직렬화합니다. struct.unpack()과 동일한 방식으로 작동하지만, 반복문을 사용해 각 데이터 블록을 개별적으로 처리(iterate)합니다.
  • struct.pack_into(): struct.pack()의 고급 버전으로, 네 개의 인수를 받습니다. 첫 번째는 사용할 형식, 두 번째는 데이터를 삽입할 데이터 버퍼, 세 번째는 버퍼 내 위치, 마지막은 패킹할 데이터입니다.
  • struct.unpack_from(): struct.unpack()의 고급 버전으로, 세 개의 인수를 받습니다. 첫 번째는 사용할 형식, 두 번째는 역직렬화할 데이터 버퍼, 마지막은 버퍼 내 위치입니다. 이를 통해 데이터의 특정 부분만 역직렬화할 수 있습니다.

서비스 스테이션에 있는 빛의 X 마크 쪽으로 이동하여 책상을 바라보고, integer, floatdouble 이라는 세 개의 변수를 생성하세요. 이 변수들을 사용해 struct.calcsize() 함수를 통해 각 형식의 바이트 크기를 확인할 것입니다. 예를 들어, integer 변수에는 함수에 'i'를 인수로 사용하고, float 변수에는 'f'를, double 변수에는 'd'를 인수로 사용하세요. 예시: integer = struct.calcsize('i') . 그리고 이 세 변수를 미리 작성된 write() 함수에 추가하세요.

금색 X 마크 쪽으로 이동하여 read() 함수를 사용해 새 농지의 데이터를 수집하세요. 그리고 나서 나중에 사용할 자원(Resources), 면적(Size), 예상치(Estimate) 등의 데이터 포인트와 형식을 기록해 두세요. 기록을 마친 후 파란 카펫 위에 있는 빛의 X 마크 쪽으로 이동하여 blue_data 라는 변수를 생성하세요.

blue_data 변수에는 이전에 기록한 형식과 값을 인수로 하여 struct.pack() 함수의 반환 값을 저장하세요. 형식을 작성할 때 여러 형식들을 하나의 단위로 ‘패킹’해야 합니다. 예를 들어, 정수 형식은 이전에 설명한 대로 'i'로 표기되며, 만약 세 개의 정수 데이터를 추가한다면 'iii'로 작성합니다. 같은 방식으로, 만약 정수, 실수, 더블을 차례로 추가한다면 'ifd'로 작성됩니다. 데이터를 추가할 때는 각 값을 개별적인 인수로 넘겨야 합니다. 전체 예시는 다음과 같습니다:

data_1 = 8 # 정수 data_2 = 2.25 # 실수 data_3 = 900.702938103 # 더블 blue_data = struct.pack('ifd', data_1, data_2, data_3)

struct.pack() 함수는 데이터의 포맷을 유연하게 설정하고, 동시에 여러 데이터 포인트를 직렬화할 수 있도록 해줍니다. 위 예제를 기반으로 이전에 기록한 데이터를 추가하세요. display() 함수에 blue_data 를 인수로 전달하여 패킹된 데이터를 확인합니다.

파란 카펫 위의 어두운 X 마크 쪽으로 이동하여 터미널을 바라보고, blue_unpack라는 변수를 생성한 후 struct.unpack() 함수의 반환 값을 저장하세요. 인수로는 데이터를 패킹할 때 사용했던 동일한 형식과 blue_data 변수를 사용합니다. 형식은 struct.pack() 함수와 동일한 방식으로 작성되므로 직렬화한 데이터를 동일한 방식으로 역직렬화할 수 있습니다. 그리고 write() 함수에 blue_unpack 을 인수로 전달하여 이전에 패킹한 데이터를 검증하세요.

같은 위치에서 struct.iter_unpack() 함수를 사용합니다. 이 함수는 struct.unpack()과 동일한 인수를 받지만, 이제는 for 루프로 데이터를 순회(iterate)하며 처리합니다. 함수 코드는 다음과 같습니다:

for values in struct.iter_unpack(-insert value-, -insert value-): player.speak(values)

누락된 인수에는 struct.unpack()에 사용했던 동일한 값을 넣으세요. 즉, 사용 방법은 동일한 함수의 변형입니다.

빨간 카펫 위의 금색 X 마크 쪽으로 이동하여 책상을 바라보고, read() 함수를 사용해 농작물의 수량 데이터를 확인하세요. 그리고 각 농작물의 수량과 해당 형식을 모두 기록해 두세요. 이후 빨간 카펫 위의 빛의 X 마크 쪽으로 이동하여 buffer라는 객체를 생성하고, bytearray(16) 값을 대입하세요. 이는 데이터를 수동으로 저장할 수 있는 바이트들의 모음입니다. 인수로 주어진 숫자 16buffer 객체에 저장할 수 있는 바이트 수를 의미합니다.

struct.pack_into() 함수를 사용하여 생성한 buffer 객체를 채우세요. 이 함수는 반환 값을 별도의 변수에 저장할 필요 없이, 데이터를 직접 buffer 객체에 삽입합니다. 이전에 기록한 모든 농작물 데이터 포인트에 대해 이 함수를 사용하여 인수를 적절히 채워 넣으세요.

예를 들어, 첫 번째 농작물 값의 경우 해당 형식, 바이트 위치, 그리고 수량이 제공됩니다. 첫 번째 인수로 형식을, 두 번째 인수로 데이터를 삽입할 buffer 객체를, 세 번째 인수로 buffer 내 삽입 위치를, 마지막 인수로 직렬화할 값을 넣으세요.

struct.pack_into('i', buffer, 0, 82)

buffer 객체는 앞서 언급한 대로 16바이트를 가지고 있으며, 위 코드에서 정수 형식은 4바이트를 사용하고 위치 0부터 삽입됩니다. 이는 데이터가 buffer에 삽입된 후, 위치 0~3은 82로 차지되어 있어 12바이트만 남는다는 의미입니다. 이전에 기록한 모든 농작물 데이터 포인트(총 3개)에 대해 이 작업을 수행하세요. 마지막으로 display() 함수에 buffer 를 인수로 전달하여 직렬화된 데이터를 출력합니다.

빨간 카펫 위의 어두운 X 마크 쪽으로 이동하여 터미널을 바라보고, 이번에는 역직렬화를 진행하여 데이터가 올바르게 저장되었는지 확인합니다. lettuce, carrots, melons 라는 세 개의 변수를 생성하고, 각 데이터 포인트를 개별적으로 언패킹하세요. 각 변수에는 struct.unpack_from() 함수의 반환 값을 저장하고, 인수로 이전에 사용했던 데이터를 사용합니다. 첫 번째 인수로 형식을, 두 번째로는 역직렬화할 buffer 객체, 마지막으로는 역직렬화할 buffer 내 위치를 지정합니다. 예시:

lettuce = struct.unpack_from('i', buffer, 0)

이 데이터는 이전에 패킹된 데이터를 역직렬화한 결과로, 나머지 두 변수도 동일하게 처리한 후, write() 함수에 lettuce, carrots, melons 를 인수로 전달하여 레벨을 완료하세요.

코드북