struct — Интерпретация байтов как упакованных двоичных данных
Исходный код: Lib/struct.py
Этот модуль выполняет преобразования между значениями Python и C-структурами, представленными в виде объектов Python bytes. Это можно использовать для обработки двоичных данных, хранящихся в файлах или полученных из сетевых подключений, среди других источников. Он использует Строки формата в качестве компактных описаний структуры C-структур и предполагаемого преобразования в/из значения Python.
Примечание
По умолчанию результат упаковки заданной C-структуры включает байты заполнения, чтобы поддерживать правильное выравнивание для вовлечённых C-типов; аналогично, при распаковке учитывается выравнивание. Такое поведение выбрано для того, чтобы байты упакованной структуры точно соответствовали расположению в памяти соответствующей C-структуры. Чтобы обработать платформенно-независимые форматы данных или опустить неявные байты заполнения, используйте standard размер и выравнивание вместо native размера и выравнивания: см. Порядок байтов, размер и выравнивание для подробностей.
Несколько struct функций (и методов Struct) принимают аргумент buffer. Он относится к объектам, которые реализуют Протокол буфера и предоставляют либо читаемый, либо читаемо-записываемый буфер. Наиболее распространённые типы, используемые для этой цели, — это bytes и bytearray, но многие другие типы, которые можно рассматривать как массив байтов, реализуют протокол буфера, так что их можно читать/заполнять без дополнительной копирования из объекта bytes.
7.1.1. Функции и исключения
Модуль определяет следующие исключения и функции:
-
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. Результатом является кортеж, даже если он содержит ровно один элемент. Размер буфера в байтах должен соответствовать размеру, требуемому форматом, как отражено вcalcsize().
-
struct.unpack_from(fmt, buffer, offset=0) -
Распаковывает из buffer, начиная с позиции offset, в соответствии со строкой формата fmt. Результатом является кортеж, даже если он содержит ровно один элемент. Размер буфера в байтах, минус offset, должен быть по крайней мере таким, который требуется форматом, как отражено в
calcsize().
-
struct.iter_unpack(fmt, buffer) -
Итеративно распаковывает из буфера buffer в соответствии со строкой формата fmt. Эта функция возвращает итератор, который будет читать одинаковые по размеру части из буфера, пока все его содержимое не будет израсходовано. Размер буфера в байтах должен быть кратным размеру, требуемому форматом, как отражено в
calcsize().В каждой итерации возвращается кортеж, указанный строкой формата.
Введено в версии 3.4.
-
struct.calcsize(fmt) -
Возвращает размер структуры (и, следовательно, объекта bytes, созданного
pack(fmt, ...)) соответствующей строке формата fmt.
7.1.2. Строки формата
Строки формата — это механизм, используемый для указания ожидаемой структуры при упаковке и распаковке данных. Они строятся из Символов формата, которые указывают тип данных, подлежащих упаковке/распаковке. Кроме того, есть специальные символы для управления Порядком байтов, размером и выравниванием.
7.1.2.1. Порядок байтов, размер и выравнивание
По умолчанию C-типы представляются в родном формате и порядке байтов машины, и правильно выравниваются путём пропуска байтов заполнения, если это необходимо (в соответствии с правилами, используемыми компилятором C).
В качестве альтернативы, первый символ строки формата может использоваться для указания порядка байтов, размера и выравнивания упаковываемых данных в соответствии со следующей таблицей:
Символ | Порядок байтов | Размер | Выравнивание |
|---|---|---|---|
| родной | родной | родной |
| родной | стандартный | нет |
| малый порядок байтов | стандартный | нет |
| большой порядок байтов | стандартный | нет |
| сетевой (= большой порядок байтов) | стандартный | нет |
Если первый символ не является одним из этих, '@' принимается по умолчанию.
Родной порядок байтов — это порядок байтов «малый» или «большой» в зависимости от системы-хозяина. Например, Intel x86 и AMD64 (x86-64) — «малый порядок байтов»; Motorola 68000 и PowerPC G5 — «большой порядок байтов»; ARM и Intel Itanium имеют переключаемый порядок байтов (двунаправленный). Используйте sys.byteorder для проверки порядка байтов вашей системы.
Родные размер и выравнивание определяются с помощью выражения sizeof компилятора C. Это всегда комбинируется с родным порядком байтов.
Стандартный размер зависит только от символа формата; см. таблицу в разделе Символы формата.
Обратите внимание на разницу между '@' и '=': оба используют родной порядок байтов, но размер и выравнивание последнего стандартизированы.
Формат '!' доступен для тех несчастных, кто не может вспомнить, является ли сетевой порядок байтов «большим» или «малым».
Нет способа указать неродной порядок байтов (вынужденное переключение байтов); используйте соответствующий выбор '<' или '>'.
Примечания:
- Заполнение добавляется только между последовательными членами структуры. Заполнение не добавляется в начале или в конце закодированной структуры.
- Заполнение не добавляется при использовании неродного размера и выравнивания, например, с помощью ‘<’, ‘>’, ‘=’, и ‘!’.
- Для выравнивания конца структуры к требованию выравнивания определённого типа, завершите формат кодом для этого типа с повторением нулевого значения. См. Примеры.
7.1.2.2. Символы формата
Символы формата имеют следующее значение; преобразование между значениями C и Python должно быть очевидным, учитывая их типы. Столбец «Стандартный размер» относится к размеру упакованного значения в байтах при использовании стандартного размера; то есть, когда строка формата начинается с одного из '<', '>', '!' или '='. При использовании родного размера размер упакованного значения зависит от платформы.
Формат | Тип C | Тип Python | Стандартный размер | Примечания |
|---|---|---|---|---|
| байт заполнения | нет значения | ||
|
| байты длиной 1 | 1 | |
|
| целое число | 1 | (1),(3) |
|
| целое число | 1 | (3) |
|
| логическое значение | 1 | (1) |
|
| целое число | 2 | (3) |
|
| целое число | 2 | (3) |
|
| целое число | 4 | (3) |
|
| целое число | 4 | (3) |
|
| целое число | 4 | (3) |
|
| целое число | 4 | (3) |
|
| целое число | 8 | (2), (3) |
|
| целое число | 8 | (2), (3) |
|
| целое число | (4) | |
|
| целое число | (4) | |
| (7) | вещественное число | 2 | (5) |
|
| вещественное число | 4 | (5) |
|
| вещественное число | 8 | (5) |
|
| байты | ||
|
| байты | ||
|
| целое число | (6) |
Изменено в версии 3.3: Добавлена поддержка форматов 'n' и 'N'.
Изменено в версии 3.6: Добавлена поддержка формата 'e'.
Примечания:
- Код преобразования
'?'соответствует типу_Bool, определённому в C99. Если этот тип недоступен, он моделируется с помощьюchar. В стандартном режиме он всегда представлен одним байтом. - Коды преобразования
'q'и'Q'доступны только в режиме native, если компилятор платформы C поддерживает Clong long, или, на Windows,__int64Они всегда доступны в стандартных режимах. -
При попытке упаковать нецелое значение с помощью любого из кодов целого типа, если нецелое значение имеет метод
__index__(), то этот метод вызывается для преобразования аргумента в целое число перед упаковкой.Изменено в версии 3.2: Использование метода
__index__()для нецелых значений появилось в 3.2. - Коды преобразования
'n'и'N'доступны только для размера native (выбран по умолчанию или с символом порядка байтов'@'). Для стандартного размера вы можете использовать любой другой целочисленный формат, подходящий для вашей задачи. - Для кодов преобразования
'f','d'и'e'упакованное представление использует формат IEEE 754 binary32, binary64 или binary16 (соответственно, для'f','d'или'e'), независимо от используемого платформой формата с плавающей точкой. - Символ формата
'P'доступен только для порядка байтов native (выбран по умолчанию или с символом порядка байтов'@'). Символ порядка байтов'='выбирает использование порядка little-endian или big-endian в зависимости от хост-системы. Модуль struct не интерпретирует это как порядок native, поэтому формат'P'недоступен. - Тип IEEE 754 binary16 «половинной точности» был введён в 2008 году в переработанном стандарте IEEE 754. Он имеет бит знака, 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 native или стандартного, а любое ненулевое значение будет True при распаковке.
7.1.2.3. Примеры
Примечание
Все примеры предполагают порядок байтов, размер и выравнивание native на машине с 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'
Это работает только в случае использования native размера и выравнивания; стандартный размер и выравнивание не навязывают никакого выравнивания.
См. также
7.1.3. Классы
Модуль 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.
-
© 2001–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.6/library/struct.html