struct — Интерпретация байтов как упакованных двоичных данных
Исходный код: Lib/struct.py
Этот модуль выполняет преобразования между значениями Python и C-структурами, представленными в Python bytes объектах. Это может быть использовано при работе с двоичными данными, хранящимися в файлах или полученными из сетевых соединений, среди прочего. Он использует Строки формата в качестве компактных описаний структуры C-структур и предполагаемого преобразования в/из значения Python.
Примечание
По умолчанию, результат упаковки заданной C-структуры включает байты дополнения для сохранения правильного выравнивания для задействованных типов C; аналогично, при распаковке учитывается выравнивание. Такое поведение выбрано для того, чтобы байты упакованной структуры точно соответствовали расположению в памяти соответствующей C-структуры. Чтобы обрабатывать платформонезависимые форматы данных или опустить неявные байты дополнения, используйте standard размер и выравнивание вместо native размера и выравнивания: см. Порядок байтов, размер и выравнивание для получения подробностей.
Несколько struct функций (и методов Struct) принимают аргумент buffer. Это относится к объектам, которые реализуют Протокол буфера и предоставляют либо читаемый, либо читаемо-записываемый буфер. Наиболее распространенные типы для этой цели — bytes и bytearray, но многие другие типы, которые могут быть представлены как массив байтов, реализуют протокол буфера, так что их можно читать/заполнять без дополнительного копирования из bytes объекта.
Функции и исключения
Модуль определяет следующее исключение и функции:
-
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.
Строки формата
Строки формата — механизм, используемый для указания ожидаемой структуры при упаковке и распаковке данных. Они построены из Символов формата, которые определяют тип данных, упаковываемых/распаковываемых. Кроме того, есть специальные символы для управления Порядком байтов, размером и выравниванием.
Порядок байтов, размер и выравнивание
По умолчанию, типы C представлены в родном формате и порядке байтов машины и правильно выровнены путем пропуска байтов дополнения, если необходимо (в соответствии с правилами, используемыми компилятором C).
В качестве альтернативы, первый символ строки формата может быть использован для указания порядка байтов, размера и выравнивания упакованных данных в соответствии со следующей таблицей:
Символ | Порядок байтов | Размер | Выравнивание |
|---|---|---|---|
| родной | родной | родной |
| родной | стандартный | нет |
| маленький порядок байтов | стандартный | нет |
| большой порядок байтов | стандартный | нет |
| сетевой (= большой порядок байтов) | стандартный | нет |
Если первый символ не является одним из этих, то используется '@'.
Родной порядок байтов — большой или маленький, в зависимости от хост-системы. Например, Intel x86 и AMD64 (x86-64) используют маленький порядок байтов; Motorola 68000 и PowerPC G5 — большой порядок байтов; ARM и Intel Itanium имеют переключаемый порядок байтов (двунаправленный). Используйте sys.byteorder для проверки порядка байтов вашей системы.
Родные размер и выравнивание определяются с помощью выражения компилятора C sizeof. Это всегда сочетается с родным порядком байтов.
Стандартный размер зависит только от символа формата; см. таблицу в разделе Символы формата.
Обратите внимание на разницу между '@' и '='. Оба используют родной порядок байтов, но размер и выравнивание последнего стандартизированы.
Форма '!' представляет собой сетевой порядок байтов, который всегда является большим порядком байтов, как определено в IETF RFC 1700.
Нет способа указать неродной порядок байтов (принудительно переставлять байты); используйте соответствующий выбор '<' или '>'.
Примечания:
- Дополнение добавляется только между последовательными членами структуры. Никакое дополнение не добавляется в начале или в конце закодированной структуры.
- При использовании неродного размера и выравнивания, например, с помощью ‘<’, ‘>’, ‘=’, и ‘!’, дополнение не добавляется.
- Чтобы выровнять конец структуры по требованиям выравнивания конкретного типа, завершите формат кодом этого типа с повтором 0. См. Примеры.
Символы форматирования
Символы форматирования имеют следующее значение; преобразование между значениями C и Python должно быть очевидным, учитывая их типы. Столбец «Стандартный размер» относится к размеру упакованного значения в байтах при использовании стандартного размера; то есть, когда строка формата начинается с одного из '<', '>', '!' или '='. При использовании размера по умолчанию размер упакованного значения зависит от платформы.
Формат | Тип C | Тип Python | Стандартный размер | Примечания |
|---|---|---|---|---|
| байт заполнения | нет значения | ||
|
| байты длиной 1 | 1 | |
|
| целое число | 1 | (1), (2) |
|
| целое число | 1 | (2) |
|
| булево | 1 | (1) |
|
| целое число | 2 | (2) |
|
| целое число | 2 | (2) |
|
| целое число | 4 | (2) |
|
| целое число | 4 | (2) |
|
| целое число | 4 | (2) |
|
| целое число | 4 | (2) |
|
| целое число | 8 | (2) |
|
| целое число | 8 | (2) |
|
| целое число | (3) | |
|
| целое число | (3) | |
| (6) | вещественное число | 2 | (4) |
|
| вещественное число | 4 | (4) |
|
| вещественное число | 8 | (4) |
|
| байты | ||
|
| байты | ||
|
| целое число | (5) |
Изменено в версии 3.3: Добавлена поддержка форматов 'n' и 'N'.
Изменено в версии 3.6: Добавлена поддержка формата 'e'.
Примечания:
- Код преобразования
'?'соответствует типу_Bool, определенному в C99. Если этот тип недоступен, он моделируется с помощьюchar. В стандартном режиме он всегда представляется одним байтом. -
При попытке упаковать нецелое число с помощью любого из кодов преобразования целых чисел, если нецелое число имеет метод
__index__(), то этот метод вызывается для преобразования аргумента в целое число перед упаковкой.Изменено в версии 3.2: Использование метода
__index__()для нецелых чисел является новым в 3.2. - Символы преобразования
'n'и'N'доступны только для размера по умолчанию (выбранного по умолчанию или с символом порядка байтов'@'). Для стандартного размера можно использовать любой из других форматов целых чисел, подходящих для вашего приложения. - Для символов преобразования
'f','d'и'e', упакованное представление использует формат IEEE 754 binary32, binary64 или binary16 (соответственно для'f','d'или'e'), независимо от формата чисел с плавающей точкой, используемого платформой. - Символ формата
'P'доступен только для родного порядка байтов (выбранного по умолчанию или с символом порядка байтов'@'). Символ порядка байтов'='выбирает использование порядка little-endian или big-endian в зависимости от системы. Модуль struct не интерпретирует это как родной порядок, поэтому формат'P'недоступен. - Тип IEEE 754 binary16 «полуточной точности» был введен в пересмотре стандарта IEEE 754 2008 года. Он имеет бит знака, 5-битный показатель и 11-битную точность (с 10 битами, хранящимися явно) и может представлять числа примерно от
6.1e-05до6.5e+04с полной точностью. Этот тип не широко поддерживается компиляторами C: на типичной машине для хранения можно использовать unsigned short, но не для математических операций. Подробную информацию см. на странице Википедии о формате чисел с плавающей запятой полуточной точности.
Символ формата может предшествовать целочисленному повторяющемуся счетчику. Например, строка формата '4h' означает то же самое, что и 'hhhh'.
Пробельные символы между форматами игнорируются; однако счетчик и его формат не должны содержать пробелов.
Для символа формата 's' счетчик интерпретируется как длина байтов, а не как повторяющийся счетчик, как для других символов формата; например, '10s' означает одну строку из 10 байтов, а '10c' означает 10 символов. Если счетчик не указан, он по умолчанию равен 1. При упаковке строка усекается или заполняется нулевыми байтами, чтобы она подходила. При распаковке полученный объект 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(), слишком длинная (длиннее, чем счетчик минус 1), хранятся только начальные count-1 байтов строки. Если строка короче count-1, она дополняется нулевыми байтами так, чтобы использовалось ровно count байтов. Обратите внимание, что для unpack() символ формата 'p' потребляет count байтов, но возвращаемая строка никогда не может содержать более 255 байтов.
Для символа формата '?' возвращаемое значение равно True или False. При упаковке используется истинностное значение объекта-аргумента. При упаковке будет использовано значение 0 или 1 в представлении bool по умолчанию или стандартном, а любое ненулевое значение будет True при распаковке.
Примеры
Примечание
Все примеры предполагают родной порядок байтов, размер и выравнивание на машине с 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', 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' задает два байта заполнения в конце, предполагая, что длинные целые числа выровнены по границам в 4 байта:
>>> pack('llh0l', 1, 2, 3)
b'\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00'
Это работает только при использовании родного размера и выравнивания; стандартный размер и выравнивание не накладывают никаких ограничений на выравнивание.
Классы
Модуль struct также определяет следующий тип:
-
class struct.Struct(format) -
Возвращает новый объект Struct, который записывает и считывает двоичные данные в соответствии со строкой формата format. Создание объекта 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.
-
© 2001–2022 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.8/library/struct.html