Содержание страницы
struct – Интерпретация байтов как упакованных двоичных данных¶struct – Interpret bytes as packed binary data
Исходный код: Lib/struct.py
Этот модуль преобразует значения Python в C-структуры, представленные как объекты bytes Python, и обратно. Компактные строки формата описывают предполагаемые преобразования значений Python. Функции и объекты модуля могут использоваться для двух в значительной степени разных задач: обмена данными с внешними источниками (файлами или сетевыми соединениями) или передачи данных между приложением Python и уровнем C.
Примечание
Если символ префикса не указан, по умолчанию используется собственный (native) режим. Он упаковывает или распаковывает данные в зависимости от платформы и компилятора, на которых был собран интерпретатор Python. Результат упаковки заданной C-структуры содержит выравнивающие байты (pad bytes), которые обеспечивают правильное выравнивание для используемых типов C; аналогично, при распаковке учитывается выравнивание. В отличие от этого, при обмене данными с внешними источниками программист отвечает за определение порядка байтов и заполнения между элементами. Подробнее см. Порядок байтов, размер и выравнивание.
Некоторые функции struct (и методы Struct) принимают аргумент buffer (буфер). Он ссылается на объекты, реализующие протокол буфера и предоставляющие буфер для чтения или чтения-записи. Наиболее распространённые типы, используемые для этой цели, – bytes и bytearray, но многие другие типы, которые можно рассматривать как массив байтов, реализуют протокол буфера, поэтому их можно читать/заполнять без дополнительного копирования из объекта bytes.
Функции и исключения¶Functions and Exceptions
Модуль определяет следующие исключения и функции:
- exception struct.error¶
Исключение, вызываемое в различных ситуациях; аргумент – строка, описывающая, что не так.
- struct.pack(format, v1, v2, ...)¶
Возвращает объект bytes, содержащий значения v1, v2, …, упакованные в соответствии со строкой формата format. Аргументы должны точно соответствовать значениям, требуемым форматом.
- struct.pack_into(format, buffer, offset, v1, v2, ...)¶
Упаковывает значения v1, v2, … в соответствии со строкой формата format и записывает упакованные байты в буфер buffer, начиная с позиции offset. Обратите внимание, что offset – обязательный аргумент.
- struct.unpack(format, buffer)¶
Распаковывает из буфера buffer (предположительно упакованного с помощью
pack(format, ...)) в соответствии со строкой формата format. Результат – кортеж, даже если он содержит ровно один элемент. Размер буфера в байтах должен соответствовать размеру, требуемому форматом, отражённомуcalcsize().
- struct.unpack_from(format, /, buffer, offset=0)¶
Распаковывает из buffer, начиная с позиции offset, в соответствии со строкой формата format. Результат – кортеж, даже если он содержит ровно один элемент. Размер буфера в байтах, начиная с позиции offset, должен быть не меньше размера, требуемого форматом, отражённого
calcsize().
- struct.iter_unpack(format, buffer)¶
Итеративно распаковывает из буфера buffer в соответствии со строкой формата format. Эта функция возвращает итератор, который будет читать из буфера блоки одинакового размера, пока всё его содержимое не будет израсходовано. Размер буфера в байтах должен быть кратен размеру, требуемому форматом, отражённому
calcsize().Каждая итерация возвращает кортеж, как указано в строке формата.
Добавлено в версии 3.4.
- struct.calcsize(format)¶
Возвращает размер структуры (и, следовательно, объекта bytes, полученного с помощью
pack(format, ...)), соответствующий строке формата format.
Строки формата¶Format Strings
Строки формата описывают расположение данных при упаковке и распаковке. Они состоят из символов формата, которые определяют тип упаковываемых/распаковываемых данных. Кроме того, специальные символы управляют порядком байтов, размером и выравниванием. Каждая строка формата состоит из необязательного символа префикса, описывающего общие свойства данных, и одного или нескольких символов формата, описывающих фактические значения данных и заполнение.
Порядок байтов, размер и выравнивание¶Byte Order, Size, and Alignment
По умолчанию типы C представляются в собственном формате и порядке байтов машины и правильно выравниваются с пропуском выравнивающих байтов при необходимости (в соответствии с правилами, используемыми компилятором C). Такое поведение выбрано, чтобы байты упакованной структуры точно соответствовали расположению в памяти соответствующей структуры C. Выбор между использованием собственного порядка байтов и выравнивания или стандартных форматов зависит от приложения.
В качестве альтернативы, первый символ строки формата может использоваться для указания порядка байтов, размера и выравнивания упакованных данных, как показано в следующей таблице:
Символ |
Порядок байтов |
Размер |
Выравнивание |
|---|---|---|---|
|
собственный |
собственный |
собственный |
|
собственный |
стандартный |
нет |
|
little-endian |
стандартный |
нет |
|
big-endian |
стандартный |
нет |
|
сетевой порядок байт (= big-endian) |
стандартный |
нет |
Если первый символ не один из этих, предполагается '@'.
Примечание
Число 1023 (0x3ff в шестнадцатеричной системе) имеет следующие представления в байтах:
03 ffв big-endian (>)ff 03в little-endian (<)
Пример на Python:
>>> import struct
>>> struct.pack('>h', 1023)
b'\x03\xff'
>>> struct.pack('<h', 1023)
b'\xff\x03'
Собственный порядок байт может быть big-endian или little-endian в зависимости от системы. Например, Intel x86, AMD64 (x86-64) и Apple M1 используют little-endian; IBM z и многие устаревшие архитектуры – big-endian. Используйте sys.byteorder для проверки порядка байт вашей системы.
Собственный размер и выравнивание определяются с помощью выражения sizeof компилятора C. Это всегда используется вместе с собственным порядком байт.
Стандартный размер зависит только от символа формата; см. таблицу в разделе Символы формата.
Обратите внимание на различие между '@' и '=': оба используют собственный порядок байт, но размер и выравнивание второго стандартизированы.
Форма '!' представляет сетевой порядок байт, который всегда является big-endian, как определено в IETF RFC 1700.
Нет способа указать несобственный порядок байт (принудительную перестановку байт); используйте соответствующий выбор из '<' или '>'.
Примечания:
Заполнение автоматически добавляется только между последовательными членами структуры. Начало и конец закодированной структуры не дополняются.
Заполнение не добавляется при использовании несобственного размера и выравнивания, например, с ‘<’, ‘>’, ‘=’ и ‘!’.
Чтобы выровнять конец структуры по требованию выравнивания конкретного типа, завершите формат кодом этого типа с нулевым количеством повторений. См. Примеры.
Символы формата¶Format Characters
Символы формата имеют следующее значение; преобразование между значениями C и Python должно быть очевидным, исходя из их типов. Столбец «Стандартный размер» указывает размер упакованного значения в байтах при использовании стандартного размера; то есть когда строка формата начинается с одного из '<', '>', '!' или '='. При использовании собственного размера размер упакованного значения зависит от платформы.
Формат |
Тип C |
Тип Python |
Стандартный размер |
Примечания |
|---|---|---|---|---|
|
байт заполнения |
нет значения |
(7) |
|
|
char |
строка байт длиной 1 |
1 |
|
|
signed char |
int |
1 |
(2) |
|
unsigned char |
int |
1 |
(2) |
|
_Bool |
bool |
1 |
(1) |
|
short |
int |
2 |
(2) |
|
unsigned short |
int |
2 |
(2) |
|
int |
int |
4 |
(2) |
|
unsigned int |
int |
4 |
(2) |
|
long |
int |
4 |
(2) |
|
unsigned long |
int |
4 |
(2) |
|
long long |
int |
8 |
(2) |
|
unsigned long long |
int |
8 |
(2) |
|
|
int |
(2), (3) |
|
|
|
int |
(2), (3) |
|
|
_Float16 |
float |
2 |
(4), (6) |
|
float |
float |
4 |
(4) |
|
double |
float |
8 |
(4) |
|
float complex |
complex |
8 |
(10) |
|
double complex |
комплексное число |
16 |
(10) |
|
char[] |
bytes |
(9) |
|
|
char[] |
bytes |
(8) |
|
|
void* |
int |
(2), (5) |
Изменено в версии 3.3: Добавлена поддержка форматов 'n' и 'N'.
Изменено в версии 3.6: Добавлена поддержка формата 'e'.
Изменено в версии 3.14: Добавлена поддержка форматов 'F' и 'D'.
См. также
Модули array и ctypes,
а также сторонние модули, такие как numpy,
используют похожие, но немного отличающиеся коды типов.
Примечания:
Код преобразования
'?'соответствует типу _Bool, определённому стандартами C начиная с C99. В стандартном режиме он представляется одним байтом.При попытке упаковать нецелое число с использованием любого из кодов преобразования целых чисел, если нецелое число имеет метод
__index__(), то этот метод вызывается для преобразования аргумента в целое число перед упаковкой.Изменено в версии 3.2: Добавлено использование метода
__index__()для нецелых чисел.Коды преобразования
'n'и'N'доступны только для родного размера (выбранного по умолчанию или с символом порядка байтов'@'). Для стандартного размера можно использовать любой из других целочисленных форматов, который подходит для приложения.Для кодов преобразования
'f','d'и'e'упакованное представление использует форматы IEEE 754 binary32, binary64 или binary16 (для'f','d'или'e'соответственно), независимо от формата чисел с плавающей запятой, используемого платформой.Символ формата
'P'доступен только для родного порядка байтов (выбранного по умолчанию или с символом порядка байтов'@'). Символ порядка байтов'='выбирает порядок little- или big-endian в зависимости от хост-системы. Модуль struct не интерпретирует это как родной порядок, поэтому формат'P'недоступен.Тип IEEE 754 binary16 «половинной точности» был введён в редакции 2008 года стандарта IEEE 754. Он имеет знаковый бит, 5-битную экспоненту и 11-битную точность (с 10 явно хранимыми битами), и может представлять числа от примерно
6.1e-05до6.5e+04с полной точностью. Этот тип не широко поддерживается компиляторами C: он доступен как тип _Float16, если компилятор поддерживает Приложение H стандарта C23. На типичной машине для хранения можно использовать unsigned short, но не для математических операций. См. страницу Википедии о формате половинной точности с плавающей запятой для получения дополнительной информации.При упаковке
'x'вставляет один нулевой байт (NUL).Символ формата
'p'кодирует «строку Паскаля», то есть короткую строку переменной длины, хранящуюся в фиксированном количестве байтов, заданном счётчиком. Первым сохраняется байт длины строки или 255, в зависимости от того, что меньше. Затем идут байты строки. Если байтовая строка, переданная вpack(), слишком длинная (длиннее, чем счётчик минус 1), сохраняются только первыеcount-1байтов строки. Если байтовая строка корочеcount-1, она дополняется нулевыми байтами, чтобы было использовано ровно count байтов. Обратите внимание, что дляunpack()символ формата'p'потребляетcountбайтов, но возвращаемый объектbytesникогда не может содержать более 255 байтов. При упаковке принимаются аргументы типовbytesиbytearray.Для символа формата
's'счётчик интерпретируется как длина байтовой строки, а не как количество повторений, как для других символов формата; например,'10s'означает одну строку из 10 байт, отображаемую в или из одного байтового объекта Python, тогда как'10c'означает 10 отдельных однобайтовых символьных элементов (например,cccccccccc), отображаемых в или из десяти разных байтовых объектов Python. (См. Примеры для конкретной демонстрации различия.) Если счётчик не указан, по умолчанию он равен 1. При упаковке байтовая строка усекается или дополняется нулевыми байтами по необходимости, чтобы она подошла. При распаковке результирующий объектbytesвсегда имеет ровно указанное количество байт. Как частный случай,'0s'означает одну пустую байтовую строку (в то время как'0c'означает 0 символов). При упаковке принимаются аргументы типовbytesиbytearray.Для символов формата
'F'и'D'упакованное представление использует форматы IEEE 754 binary32 и binary64 для компонентов комплексного числа, независимо от формата чисел с плавающей запятой, используемого платформой. Обратите внимание, что комплексные типы (FиD) доступны безусловно, несмотря на то, что комплексные типы являются опциональной возможностью в C. Как указано в стандарте C11, каждый комплексный тип представлен массивом из двух элементов C, содержащим соответственно действительную и мнимую части.
Символу формата может предшествовать целочисленный счётчик повторений. Например,
строка формата '4h' означает то же самое, что и 'hhhh'.
Пробельные символы между форматами игнорируются; однако счётчик и его формат не должны содержать пробелов.
При упаковке значения x с использованием одного из целочисленных форматов ('b',
'B', 'h', 'H', 'i', 'I', 'l', 'L',
'q', 'Q'), если x выходит за допустимый диапазон для этого формата,
то вызывается struct.error.
Изменено в версии 3.1: Ранее некоторые из целочисленных форматов выполняли перенос значений за диапазон и
вызывали DeprecationWarning вместо struct.error.
Для символа формата '?' возвращаемое значение – True или
False. При упаковке используется истинностное значение объекта-аргумента.
Будет упакован либо 0, либо 1 в родном или стандартном представлении bool, и
любое ненулевое значение будет True при распаковке.
Примеры¶Examples
Примечание
Примеры с родным порядком байтов (обозначенным префиксом формата '@' или
отсутствием какого-либо символа префикса) могут не совпадать с тем, что выдаёт
машина читателя, так как это зависит от платформы и компилятора.
Упакуйте и распакуйте целые числа трёх разных размеров, используя порядок big endian:
>>> from struct import *
>>> pack(">bhl", 1, 2, 3)
b'\x01\x00\x02\x00\x00\x00\x03'
>>> unpack('>bhl', b'\x01\x00\x02\x00\x00\x00\x03')
(1, 2, 3)
>>> calcsize('>bhl')
7
Попытка упаковать целое число, которое слишком велико для заданного поля:
>>> pack(">h", 99999)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
struct.error: 'h' format requires -32768 <= number <= 32767
Демонстрация различия между символами формата 's' и 'c':
>>> pack("@ccc", b'1', b'2', b'3')
b'123'
>>> pack("@3s", b'123')
b'123'
Распакованные поля можно именовать, присваивая их переменным или оборачивая результат в именованный кортеж:
>>> 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 ниже после упаковки '#' были добавлены три нулевых байта,
чтобы выровнять следующее целое число по границе четырёх байт.
В этом примере вывод был получен на машине с порядком от младшего к старшему:
>>> pack('@ci', b'#', 0x12131415)
b'#\x00\x00\x00\x15\x14\x13\x12'
>>> pack('@ic', 0x12131415, b'#')
b'\x15\x14\x13\x12#'
>>> calcsize('@ci')
8
>>> calcsize('@ic')
5
Следующая строка формата 'llh0l' приводит к добавлению двух байт выравнивания
в конце, если предполагается, что длинные целые платформы выровнены по 4-байтовым границам:
>>> pack('@llh0l', 1, 2, 3)
b'\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00'
Применения¶Applications
Существуют два основных применения модуля struct: обмен данными между Python и кодом C
внутри приложения или другого приложения, скомпилированного с тем же компилятором
(собственные форматы), и обмен данными между приложениями по согласованной схеме размещения данных
(стандартные форматы). В общем случае строки формата,
построенные для этих двух областей, различаются.
Собственные форматы¶Native Formats
При построении строк формата, имитирующих собственное размещение, компилятор
и архитектура машины определяют порядок байт и выравнивание.
В таких случаях следует использовать символ формата @, чтобы указать
собственный порядок байт и размеры данных. Внутренние байты выравнивания обычно вставляются
автоматически. Возможно, потребуется код формата с нулевым повторением
в конце строки формата для округления до правильной
байтовой границы для корректного выравнивания последовательных блоков данных.
Рассмотрим два простых примера (на 64-битной машине с порядком от младшего к старшему):
>>> calcsize('@lhl')
24
>>> calcsize('@llh')
18
Данные не выравниваются по 8-байтовой границе в конце второй строки формата без использования дополнительного выравнивания. Код формата с нулевым повторением решает эту проблему:
>>> calcsize('@llh0l')
24
Код формата 'x' можно использовать для указания повторения, но для собственных форматов лучше использовать код с нулевым повторением, например '0l'.
По умолчанию используется собственный порядок байт и выравнивание, но лучше указывать это явно с помощью префиксного символа '@'.
Стандартные форматы¶Standard Formats
При обмене данными за пределами процесса, например по сети или при хранении, будьте точны. Укажите точный порядок байт, размер и выравнивание. Не предполагайте, что они совпадают с собственным порядком конкретной машины. Например, сетевой порядок байт – от старшего к младшему, в то время как многие популярные ЦП используют порядок от младшего к старшему. Явно определяя это, пользователю не нужно заботиться об особенностях платформы, на которой выполняется его код. Первым символом обычно должен быть < или > (или !). Выравнивание – ответственность программиста. Код формата с нулевым повторением не работает. Вместо этого пользователь должен явно добавлять байты выравнивания 'x' там, где это необходимо. Возвращаясь к примерам из предыдущего раздела:
>>> calcsize('<qh6xq')
24
>>> pack('<qh6xq', 1, 2, 3) == pack('@lhl', 1, 2, 3)
True
>>> calcsize('@llh')
18
>>> pack('@llh', 1, 2, 3) == pack('<qqh', 1, 2, 3)
True
>>> calcsize('<qqh6x')
24
>>> calcsize('@llh0l')
24
>>> pack('@llh0l', 1, 2, 3) == pack('<qqh6x', 1, 2, 3)
True
Приведённые выше результаты (полученные на 64-битной машине) не гарантированно совпадут при выполнении на разных машинах. Например, примеры ниже были выполнены на 32-битной машине:
>>> calcsize('<qqh6x')
24
>>> calcsize('@llh0l')
12
>>> pack('@llh0l', 1, 2, 3) == pack('<qqh6x', 1, 2, 3)
False
Классы¶Classes
Модуль struct также определяет следующий тип:
- class struct.Struct(format)¶
Возвращает новый объект Struct, который читает и записывает двоичные данные в соответствии со строкой формата format. Создание объекта
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.
- size¶
Вычисленный размер структуры (и, следовательно, объекта bytes, создаваемого методом
pack()), соответствующийformat.
Изменено в версии 3.13: repr() структур изменилась. Теперь оно:
>>> Struct('i') Struct('i')