struct — 패킹 된 바이너리 데이터로 바이트열을 해석

소스 코드: Lib/struct.py


이 모듈은 파이썬 값과 파이썬 bytes 객체로 표현되는 C 구조체 사이의 변환을 수행합니다. 다른 소스 중에서도, 파일에 저장되었거나 네트워크 연결에서 온 바이너리 데이터를 처리하는 데 사용할 수 있습니다. 포맷 문자열을 구조체의 배치와 파이썬 값과의 변환에 대한 간결한 기술로 사용합니다.

참고

기본적으로, 주어진 C 구조체를 패킹한 결과에는 관련된 C형에 대한 적절한 정렬(alignment)을 유지하기 위해 패드(pad) 바이트가 포함됩니다; 마찬가지로, 언 패킹할 때 정렬이 고려됩니다. 이 동작은 패킹 된 구조체의 바이트열이 해당 C 구조체의 메모리 배치와 정확히 일치하도록 선택됩니다. 플랫폼 독립적인 데이터 형식을 처리하거나 묵시적 패드 바이트를 생략하려면, native 크기와 정렬 대신 standard 크기와 정렬을 사용하십시오: 자세한 내용은 바이트 순서, 크기 및 정렬을 참조하십시오.

여러 struct 함수(그리고 Struct 의 메서드)는 buffer 인자를 취합니다. 이는 버퍼 프로토콜을 구현하고 읽을 수 있거나 읽고 쓸 수 있는 버퍼를 제공하는 객체를 나타냅니다. 이 목적으로 사용되는 가장 일반적인 형은 bytesbytearray지만, 바이트 배열로 볼 수 있는 많은 다른 형이 버퍼 프로토콜을 구현하므로, bytes 객체에서 추가로 복사하지 않고도 읽고 채울 수 있습니다.

함수와 예외

이 모듈은 다음과 같은 예외와 함수를 정의합니다:

exception struct.error

여러 상황에서 발생하는 예외; 인자는 무엇이 잘못되었는지 설명하는 문자열입니다.

struct.pack(format, v1, v2, ...)

v1, v2, … 값을 포함하고 포맷 문자열 format에 따라 패킹 된 바이트열 객체를 반환합니다. 인자는 포맷이 요구하는 값과 정확히 일치해야 합니다.

struct.pack_into(format, buffer, offset, v1, v2, ...)

포맷 문자열 format에 따라 값 v1, v2, … 를 패킹하고 패킹 된 바이트열을 쓰기 가능한 버퍼 bufferoffset 위치에서부터 씁니다. offset은 필수 인자임에 유의하십시오.

struct.unpack(format, buffer)

포맷 문자열 format에 따라 버퍼 buffer(아마도 pack(format, ...)으로 패킹 된)에서 언 패킹 합니다. 정확히 하나의 항목을 포함하더라도 결과는 튜플입니다. 바이트 단위의 버퍼 크기는 (calcsize()에 의해 반영되는) 포맷이 요구하는 크기와 일치해야 합니다.

struct.unpack_from(format, /, buffer, offset=0)

포맷 문자열 format에 따라, offset 위치에서 시작하여 buffer에서 언 패킹 합니다. 정확히 하나의 항목을 포함하더라도 결과는 튜플입니다. offset 위치에서 시작하여 바이트 단위로 측정한 버퍼 크기는 (calcsize()에 의해 반영되는) 포맷이 요구하는 크기 이상이어야 합니다.

struct.iter_unpack(format, buffer)

Iteratively unpack from the buffer buffer according to the format string format. This function returns an iterator which will read equally sized chunks from the buffer until all its contents have been consumed. The buffer’s size in bytes must be a multiple of the size required by the format, as reflected by calcsize().

각 이터레이션은 포맷 문자열에 지정된 대로 튜플을 산출합니다.

버전 3.4에 추가.

struct.calcsize(format)

포맷 문자열 format에 해당하는 구조체(pack(format, ...)에 의해 생성되는 바이트열 객체)의 크기를 반환합니다.

포맷 문자열

포맷 문자열은 데이터를 패킹과 언 패킹할 때 기대되는 배치를 지정하는 데 사용되는 메커니즘입니다. 이들은 패킹/언 패킹 될 데이터형을 지정하는 포맷 문자로 구축됩니다. 또한, 바이트 순서, 크기 및 정렬을 제어하기 위한 특수 문자가 있습니다.

바이트 순서, 크기 및 정렬

기본적으로, C형은 기계의 네이티브 형식과 바이트 순서로 표현되며, 필요하면 (C 컴파일러에서 사용하는 규칙에 따라) 패드 바이트로 건너뛰어 적절하게 정렬됩니다.

또는, 다음 표에 따라, 포맷 문자열의 첫 번째 문자를 사용하여 패킹 된 데이터의 바이트 순서, 크기 및 정렬을 표시할 수 있습니다:

문자

바이트 순서

크기

정렬

@

네이티브

네이티브

네이티브

=

네이티브

표준

none

<

리틀 엔디안

표준

none

>

빅 엔디안

표준

none

!

네트워크 (= 빅 엔디안)

표준

none

첫 번째 문자가 이들 중 하나가 아니면, '@'로 가정합니다.

Native byte order is big-endian or little-endian, depending on the host system. For example, Intel x86 and AMD64 (x86-64) are little-endian; IBM z and most legacy architectures are big-endian; and ARM, RISC-V and IBM Power feature switchable endianness (bi-endian, though the former two are nearly always little-endian in practice). Use sys.byteorder to check the endianness of your system.

네이티브 크기와 정렬은 C 컴파일러의 sizeof 표현식을 사용하여 결정됩니다. 이것은 항상 네이티브 바이트 순서와 결합합니다.

표준 크기는 포맷 문자에만 의존합니다; 포맷 문자 섹션의 표를 참조하십시오.

'@''='의 차이점에 유의하십시오; 둘 다 네이티브 바이트 순서를 사용하지만, 후자는 크기와 정렬이 표준화됩니다.

'!' 형식은 IETF RFC 1700에 정의된 대로 항상 빅 엔디안인 네트워크 바이트 순서를 나타냅니다.

네이티브가 아닌 바이트 순서(강제 바이트 스와핑)를 표시하는 방법은 없습니다; '<''>'를 적절히 선택하십시오.

노트:

  1. 패딩은 연속되는 구조체 멤버 간에만 자동으로 추가됩니다. 인코딩된 구조체의 시작이나 끝에는 패딩이 추가되지 않습니다.

  2. 네이티브가 아닌 크기와 정렬을 사용할 때는 패딩이 추가되지 않습니다, 예를 들어 ‘<’, ‘>’, ‘=’ 및 ‘!’ 에서.

  3. 구조체의 끝을 특정 형의 정렬 요구 사항에 맞추려면, 반복 횟수가 0인 해당 형의 코드로 포맷을 끝내십시오. 를 참조하십시오.

포맷 문자

포맷 문자는 다음과 같은 의미가 있습니다; C와 파이썬 값 사이의 변환은 형을 주면 분명해야 합니다. ‘표준 크기’ 열은 표준 크기를 사용할 때 패킹 된 값의 크기를 바이트 단위로 나타냅니다; 즉, 포맷 문자열이 '<', '>', '!' 또는 '=' 중 하나로 시작하는 경우입니다. 네이티브 크기를 사용할 때, 패킹 된 값의 크기는 플랫폼에 따라 다릅니다.

포맷

C형

파이썬 형

표준 크기

노트

x

패드 바이트

값이 없습니다

c

char

길이가 1인 bytes

1

b

signed char

정수

1

(1), (2)

B

unsigned char

정수

1

(2)

?

_Bool

bool

1

(1)

h

short

정수

2

(2)

H

unsigned short

정수

2

(2)

i

int

정수

4

(2)

I

unsigned int

정수

4

(2)

l

long

정수

4

(2)

L

unsigned long

정수

4

(2)

q

long long

정수

8

(2)

Q

unsigned long long

정수

8

(2)

n

ssize_t

정수

(3)

N

size_t

정수

(3)

e

(6)

float

2

(4)

f

float

float

4

(4)

d

double

float

8

(4)

s

char[]

bytes

p

char[]

bytes

P

void*

정수

(5)

버전 3.3에서 변경: 'n''N' 포맷에 대한 지원이 추가되었습니다.

버전 3.6에서 변경: 'e' 포맷에 대한 지원이 추가되었습니다.

노트:

  1. '?' 변환 코드는 C99가 정의한 _Bool 형에 해당합니다. 이 형을 사용할 수 없으면, char를 사용하여 시뮬레이션 됩니다. 표준 모드에서는, 항상 1바이트로 표현됩니다.

  2. 정수 변환 코드 중 하나를 사용하여 정수가 아닌 값을 패킹하려고 할 때, 정수가 아닌 값에 __index__() 메서드가 있으면 패킹 전에 해당 메서드가 호출되어 인자를 정수로 변환합니다.

    버전 3.2에서 변경: 정수가 아닌 값에서 __index__() 메서드를 사용하는 것을 추가했습니다.

  3. 'n''N' 변환 코드는 (기본값이나 '@' 바이트 순서 문자로 선택된) 네이티브 크기에만 사용할 수 있습니다. 표준 크기의 경우, 응용 프로그램에 맞는 다른 정수 포맷을 사용할 수 있습니다.

  4. 'f', 'd''e' 변환 코드의 경우, 패킹 된 표현은 플랫폼에서 사용하는 부동 소수점 형식과 관계없이 IEEE 754 binary32, binary64 또는 binary16 형식을 사용합니다 (각각 'f', 'd' 또는 'e').

  5. 'P' 포맷 문자는 (기본값이나 '@' 바이트 순서 문자로 선택된) 네이티브 바이트 순서에만 사용할 수 있습니다. 바이트 순서 문자 '='는 호스트 시스템에 따라 리틀이나 빅 엔디안 순서를 사용하도록 선택합니다. struct 모듈은 이를 네이티브 순서로 해석하지 않아서, 'P' 형식을 사용할 수 없습니다.

  6. IEEE 754 binary16 “반 정밀도” 형은 2008년 IEEE 754 표준 개정판에서 도입되었습니다. 부호 비트, 5비트 지수 및 11비트 정밀도(10비트가 명시적으로 저장됩니다)를 가지며, 전체 정밀도에서 대략 6.1e-056.5e+04 사이의 숫자를 나타낼 수 있습니다. 이 형은 C 컴파일러에서 널리 지원되지 않습니다: 일반적인 기계에서는, unsigned short를 저장에 사용할 수 있지만, 수학 연산에는 사용할 수 없습니다. 자세한 내용은 half-precision floating-point format의 Wikipedia 페이지를 참조하십시오.

포맷 문자 앞에는 정수 반복 횟수가 올 수 있습니다. 예를 들어, 포맷 문자열 '4h''hhhh'와 정확히 같습니다.

포맷 사이의 공백 문자는 무시됩니다; 횟수와 형식 사이에는 공백이 없어야 합니다.

's' 포맷 문자의 경우, 횟수는 다른 포맷 문자와 같은 반복 횟수가 아닌 바이트열의 길이로 해석됩니다; 예를 들어, '10s'는 단일 10바이트 문자열을 의미하고, '10c'는 10문자를 의미합니다. 횟수를 지정하지 않으면, 기본값은 1입니다. 패킹의 경우, 맞도록 문자열이 잘리거나 널 바이트로 채워집니다. 언 패킹의 경우, 결과 바이트열 객체는 항상 지정된 바이트 수를 갖습니다. 특별한 경우로, '0s'는 하나의 빈 문자열을 의미합니다(반면에 '0c'는 0문자를 의미합니다).

정수 형식 ('b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q') 중 하나를 사용하여 값 x를 패킹할 때, x가 해당 포맷의 유효한 범위를 벗어나면 struct.error가 발생합니다.

버전 3.1에서 변경: 이전에는, 일부 정수 포맷은 범위를 벗어난 값을 래핑하고 struct.error 대신 DeprecationWarning을 발생시켰습니다.

'p' 포맷 문자는 “파스칼 문자열”을 인코딩하는데, 이는 카운트에 의해 주어진 고정된 바이트 수에 저장된 짧은 가변 길이 문자열을 의미합니다. 저장된 첫 번째 바이트는 문자열의 길이나 255중 작은 값입니다. 문자열의 바이트가 그 뒤에 옵니다. pack()에 전달된 문자열이 너무 길면 (횟수 빼기 1보다 길면), 문자열의 선행 count-1 바이트만 저장됩니다. 문자열이 count-1보다 짧으면, 전부 정확한 바이트 수가 되도록 널 바이트로 채워집니다. unpack()의 경우, 'p' 포맷 문자는 count 바이트를 소비하지만, 반환된 문자열은 255바이트를 초과할 수 없음에 유의하십시오.

'?' 포맷 문자의 경우, 반환 값은 TrueFalse입니다. 패킹할 때, 인자 객체의 논리값이 사용됩니다. 네이티브나 표준 bool 표현에서 0이나 1이 패킹 되고, 언 패킹할 때 모든 0이 아닌 값은 True가 됩니다.

참고

모든 예는 빅 엔디안 기계에서 네이티브 바이트 순서, 크기 및 정렬을 가정합니다.

3개의 정수를 패킹/언 패킹하는 기본 예제:

>>> from struct import *
>>> pack('hhl', 1, 2, 3)
b'\x00\x01\x00\x02\x00\x00\x00\x03'
>>> unpack('hhl', b'\x00\x01\x00\x02\x00\x00\x00\x03')
(1, 2, 3)
>>> calcsize('hhl')
8

언 패킹 된 필드는 변수에 대입하거나 결과를 네임드 튜플로 감싸서 이름을 붙일 수 있습니다:

>>> record = b'raymond   \x32\x12\x08\x01\x08'
>>> name, serialnum, school, gradelevel = unpack('<10sHHb', record)

>>> from collections import namedtuple
>>> Student = namedtuple('Student', 'name serialnum school gradelevel')
>>> Student._make(unpack('<10sHHb', record))
Student(name=b'raymond   ', serialnum=4658, school=264, gradelevel=8)

정렬 요구 사항을 충족시키는 데 필요한 패딩이 다르기 때문에 포맷 문자의 순서는 크기에 영향을 줄 수 있습니다:

>>> pack('ci', b'*', 0x12131415)
b'*\x00\x00\x00\x12\x13\x14\x15'
>>> pack('ic', 0x12131415, b'*')
b'\x12\x13\x14\x15*'
>>> calcsize('ci')
8
>>> calcsize('ic')
5

다음 포맷 'llh0l'는 long이 4바이트 경계에 정렬된다고 가정할 때 끝에 2개의 패드 바이트를 지정합니다:

>>> pack('llh0l', 1, 2, 3)
b'\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00'

이것은 네이티브 크기와 정렬이 유효한 경우에만 작동합니다; 표준 크기와 정렬은 어떤 정렬도 강제하지 않습니다.

더 보기

모듈 array

동종 데이터의 패킹 된 바이너리 저장소.

모듈 xdrlib

XDR 데이터의 패킹과 언 패킹.

클래스

struct 모듈은 또한 다음 형을 정의합니다:

class struct.Struct(format)

포맷 문자열 format에 따라 바이너리 데이터를 쓰고 읽는 새 Struct 객체를 반환합니다. Struct 객체를 한 번 만들고 메서드를 호출하는 것은 포맷 문자열을 한 번만 컴파일하면 되기 때문에 같은 포맷으로 struct 함수를 호출하는 것보다 효율적입니다.

참고

Struct 와 모듈 수준 함수에 전달된 최신 포맷 문자열의 컴파일된 버전이 캐시 되므로, 몇 가지 포맷 문자열만 사용하는 프로그램은 단일 Struct 인스턴스 재사용에 대해 신경 쓸 필요가 없습니다.

컴파일된 Struct 객체는 다음 메서드와 어트리뷰트를 지원합니다:

pack(v1, v2, ...)

pack() 함수와 동일하고, 컴파일된 포맷을 사용합니다. (len(result)size와 같게 됩니다.)

pack_into(buffer, offset, v1, v2, ...)

pack_into() 함수와 동일하고, 컴파일된 포맷을 사용합니다.

unpack(buffer)

unpack() 함수와 동일하고, 컴파일된 포맷을 사용합니다. 바이트 단위의 버퍼 크기는 size와 같아야 합니다.

unpack_from(buffer, offset=0)

unpack_from() 함수와 동일하고, 컴파일된 포맷을 사용합니다. offset 위치에서 시작하는 바이트 단위의 버퍼 크기는 size 이상이어야 합니다.

iter_unpack(buffer)

iter_unpack() 함수와 동일하고, 컴파일된 포맷을 사용합니다. 바이트 단위의 버퍼 크기는 size의 배수이어야 합니다.

버전 3.4에 추가.

format

이 Struct 객체를 구성하는 데 사용된 포맷 문자열.

버전 3.7에서 변경: 포맷 문자열형은 이제 bytes 대신 str입니다.

size

format에 해당하는 구조체(pack() 메서드에 의해 생성된 바이트열 객체)의 계산된 크기.