Документация Python неофициальный перевод
Содержание страницы

7.3. struct – Интерпретация байтов как упакованных двоичных данныхstruct – Interpret bytes as packed binary data

Этот модуль выполняет преобразования между значениями Python и C-структурами, представленными в виде объектов Python bytes. Его можно использовать для обработки двоичных данных, хранящихся в файлах или получаемых из сетевых соединений, а также других источников. Он использует строки форматирования как компактное описание структуры C-структур и предполагаемого преобразования в/из значений Python.

Примечание

По умолчанию результат упаковки заданной C-структуры включает байты заполнения для сохранения правильного выравнивания соответствующих типов C; аналогично, выравнивание учитывается при распаковке. Такое поведение выбрано для того, чтобы байты упакованной структуры точно соответствовали расположению в памяти соответствующей C-структуры. Для работы с платформонезависимыми форматами данных или для пропуска неявных байтов заполнения используйте стандартный размер и выравнивание вместо собственного размера и выравнивания: подробнее см. Порядок байтов, размер и выравнивание.

7.3.1. Функции и исключенияFunctions and Exceptions

Модуль определяет следующие исключения и функции:

exception struct.error
Исключение, вызываемое в различных ситуациях; аргумент – строка, описывающая, что не так.
struct.pack(fmt, v1, v2, ...)
Возвращает объект bytes, содержащий значения v1, v2, ..., упакованные в соответствии со строкой форматирования fmt. Аргументы должны точно соответствовать значениям, требуемым форматом.
struct.pack_into(fmt, buffer, offset, v1, v2, ...)
Упаковывает значения v1, v2, ... в соответствии со строкой формата fmt и записывает упакованные байты в буфер buffer, начиная с позиции offset. Обратите внимание: offset – обязательный аргумент.
struct.unpack(fmt, buffer)
Распаковывает из буфера buffer (предположительно упакованного с помощью pack(fmt, ...)) в соответствии со строкой форматирования fmt. Результатом является кортеж, даже если он содержит ровно один элемент. Буфер должен содержать ровно столько данных, сколько требуется форматом (len(bytes) должно равняться calcsize(fmt)).
struct.unpack_from(fmt, buffer, offset=0)
Распаковывает из buffer, начиная с позиции offset, в соответствии со строкой форматирования fmt. Результатом является кортеж, даже если он содержит ровно один элемент. buffer должен содержать как минимум столько данных, сколько требуется форматом (len(buffer[offset:]) должно быть не меньше calcsize(fmt)).
struct.calcsize(fmt)
Возвращает размер структуры (и, следовательно, объекта bytes, создаваемого pack(fmt, ...)), соответствующий строке форматирования fmt.

7.3.2. Строки форматаFormat Strings

Строки формата – это механизм, используемый для указания ожидаемого расположения данных при упаковке и распаковке. Они составляются из символов формата, которые задают тип упаковываемых/распаковываемых данных. Кроме того, существуют специальные символы для управления порядком байтов, размером и выравниванием.

7.3.2.1. Порядок байтов, размер и выравниваниеByte Order, Size, and Alignment

По умолчанию типы C представляются в собственном формате и порядке байтов машины и правильно выравниваются путём пропуска байтов заполнения при необходимости (в соответствии с правилами, используемыми компилятором C).

В качестве альтернативы, первый символ строки формата может использоваться для указания порядка байтов, размера и выравнивания упакованных данных, как показано в следующей таблице:

Символ Порядок байтов Размер Выравнивание
@ собственный собственный собственный
= собственный стандартный нет
< little-endian стандартный нет
> big-endian стандартный нет
! сетевой порядок байт (= big-endian) стандартный нет

Если первый символ не один из этих, предполагается '@'.

Собственный порядок байтов может быть big-endian или little-endian в зависимости от хост-системы. Например, Intel x86 и AMD64 (x86-64) используют little-endian; Motorola 68000 и PowerPC G5 – big-endian; ARM и Intel Itanium поддерживают переключаемый порядок байтов (bi-endian). Используйте sys.byteorder для проверки порядка байтов вашей системы.

Собственный размер и выравнивание определяются с помощью выражения sizeof компилятора C. Это всегда сочетается с собственным порядком байтов.

Стандартный размер зависит только от символа формата; см. таблицу в разделе Символы формата.

Обратите внимание на различие между '@' и '=': оба используют собственный порядок байт, но размер и выравнивание второго стандартизированы.

Форма '!' доступна для тех несчастных, кто утверждает, что не может запомнить, является ли сетевой порядок байтов big-endian или little-endian.

Нет способа указать несобственный порядок байт (принудительную перестановку байт); используйте соответствующий выбор из '<' или '>'.

Примечания:

  1. Заполнение автоматически добавляется только между последовательными членами структуры. Начало и конец закодированной структуры не дополняются.
  2. Заполнение не добавляется при использовании несобственного размера и выравнивания, например, с ‘<’, ‘>’, ‘=’ и ‘!’.
  3. Чтобы выровнять конец структуры по требованию выравнивания конкретного типа, завершите формат кодом этого типа с нулевым количеством повторений. См. Примеры.

7.3.2.2. Символы форматаFormat Characters

Символы формата имеют следующее значение; преобразование между значениями C и Python должно быть очевидным, исходя из их типов. Столбец «Стандартный размер» указывает размер упакованного значения в байтах при использовании стандартного размера; то есть когда строка формата начинается с одного из '<', '>', '!' или '='. При использовании собственного размера размер упакованного значения зависит от платформы.

Формат Тип C Тип Python Стандартный размер Примечания
x байт заполнения нет значения    
c char строка байт длиной 1 1  
b знаковый char целое число 1 (1)
B unsigned char целое число 1  
? _Bool bool 1 (2)
h short целое число 2  
H unsigned short целое число 2  
i int целое число 4  
I unsigned int целое число 4  
l long целое число 4  
L unsigned long целое число 4  
q long long целое число 8 (3)
Q unsigned long long целое число 8 (3)
f float float 4 (4)
d double float 8 (4)
s char[] байты   (1)
p char[] байты   (1)
P void * целое число   (5)

Примечания:

  1. Коды преобразования c, s и p работают с объектами bytes, но упаковка с этими кодами также поддерживает объекты str, которые кодируются с использованием UTF-8.
  2. Код преобразования '?' соответствует типу _Bool, определённому в C99. Если этот тип недоступен, он имитируется с помощью char. В стандартном режиме он всегда представлен одним байтом.
  3. Коды преобразования 'q' и 'Q' доступны в родном режиме, только если компилятор C платформы поддерживает C long long или, в Windows, __int64. Они всегда доступны в стандартных режимах.
  4. Для кодов преобразования 'f' и 'd' упакованное представление использует формат IEEE 754 binary32 (для 'f') или binary64 (для 'd'), независимо от формата чисел с плавающей запятой, используемого платформой.
  5. Символ формата 'P' доступен только для родного порядка байтов (выбранного по умолчанию или с помощью символа порядка байтов '@'). Символ порядка байтов '=' выбирает порядок little- или big-endian в зависимости от хост-системы. Модуль struct не интерпретирует это как родной порядок, поэтому формат 'P' недоступен.

Символу формата может предшествовать целочисленный счетчик повторений. Например, строка формата '4h' означает то же самое, что и 'hhhh'.

Пробельные символы между форматами игнорируются; однако счётчик и его формат не должны содержать пробелов.

Для символа формата 's' количество интерпретируется как длина строки в байтах, а не как количество повторений, как для других символов формата; например, '10s' означает одну строку длиной 10 байт, тогда как '10c' означает 10 символов. При упаковке строка усекается или дополняется нулевыми байтами по мере необходимости, чтобы соответствовать заданной длине. При распаковке результирующий объект bytes всегда содержит ровно указанное количество байт. В частном случае '0s' означает одну пустую строку (а '0c' означает 0 символов).

При упаковке значения x с использованием одного из целочисленных форматов ('b', 'B', 'h', 'H', 'i', 'I', 'l', 'L', 'q', 'Q'), если x выходит за допустимый диапазон для этого формата, то возбуждается struct.error.

Изменено в версии 3.1: В версии 3.0 некоторые целочисленные форматы обрабатывали значения, выходящие за пределы, и возбуждали DeprecationWarning вместо struct.error.

Символ формата 'p' кодирует «строку Паскаля», то есть короткую строку переменной длины, хранящуюся в фиксированном количестве байтов, заданном счетчиком. Первый сохраненный байт – это длина строки или 255, в зависимости от того, что меньше. Затем следуют байты строки. Если строка, переданная в pack(), слишком длинная (длиннее, чем count минус 1), сохраняются только первые count-1 байтов строки. Если строка короче count-1, она дополняется нулевыми байтами, так что всего используется ровно count байтов. Обратите внимание, что для unpack() символ формата 'p' потребляет count байтов, но возвращаемая строка никогда не может содержать более 255 байтов.

Для символа формата '?' возвращаемым значением является либо True, либо False. При упаковке используется истинностное значение объекта-аргумента. Будет упакован либо 0, либо 1 в нативном или стандартном представлении bool, а при распаковке любое ненулевое значение станет True.

7.3.2.3. ПримерыExamples

Примечание

Все примеры предполагают собственный порядок байтов, размер и выравнивание на машине с big-endian.

Простой пример упаковки/распаковки трёх целых чисел:

>>> 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', '*', 0x12131415)
b'*\x00\x00\x00\x12\x13\x14\x15'
>>> pack('ic', 0x12131415, '*')
b'\x12\x13\x14\x15*'
>>> calcsize('ci')
8
>>> calcsize('ic')
5

Следующий формат 'llh0l' указывает два байта заполнения в конце, при условии, что значения long выровнены по границе 4 байта:

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

Это работает только при использовании собственного размера и выравнивания; стандартный размер и выравнивание не обеспечивают никакого выравнивания.

См. также

Модуль array
Упакованное бинарное хранение однородных данных.
Модуль xdrlib
Упаковка и распаковка данных XDR.

7.3.3. КлассыClasses

Модуль struct также определяет следующий тип:

class struct.Struct(format)

Возвращает новый объект Struct, который записывает и читает двоичные данные в соответствии с строкой форматирования format. Создание объекта Struct один раз и вызов его методов более эффективно, чем вызов функций struct с той же строкой форматирования, поскольку её нужно скомпилировать только один раз.

Скомпилированные объекты Struct поддерживают следующие методы и атрибуты:

pack(v1, v2, ...)
Идентично функции pack() с использованием скомпилированного формата. (len(result) будет равно self.size.)
pack_into(buffer, offset, v1, v2, ...)
Идентично функции pack_into() с использованием скомпилированного формата.
unpack(buffer)
Идентично функции unpack() с использованием скомпилированного формата. (len(buffer) должно быть равно self.size).
unpack_from(buffer, offset=0)
Идентично функции unpack_from() с использованием скомпилированного формата. (len(buffer[offset:]) должно быть не менее self.size).
format
Строка форматирования, используемая для создания этого объекта Struct.
size
Вычисленный размер структуры (и, соответственно, объекта bytes, создаваемого методом pack()) для format.