struct — Интерпретировать байты как упакованные двоичные данные

Исходный код: Lib/struct.py.


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

Примечание

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

Некоторые функции struct (и методы Struct) принимают аргумент буфер. Это относится к объектам, реализующим Буферный протокол и предоставляющим буфер для чтения или записи. Наиболее часто для этой цели используются типы 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)

Распаковать из буфера, начиная с позиции offset, в соответствии со строкой формата format. Результатом является кортеж, даже если он содержит ровно один элемент. Размер буфера в байтах, начиная с позиции offset, должен быть не меньше размера, требуемого форматом, что отражено в строке calcsize().

struct.iter_unpack(format, buffer)

Итеративно распаковать из буфера buffer в соответствии со строкой формата format. Эта функция возвращает итератор, который будет считывать из буфера одинаковые по размеру фрагменты, пока не будет израсходовано все его содержимое. Размер буфера в байтах должен быть кратен размеру, требуемому форматом, что отражается в calcsize().

Каждая итерация дает кортеж, заданный строкой формата.

Добавлено в версии 3.4.

struct.calcsize(format)

Возвращает размер структуры (и, следовательно, байтового объекта, создаваемого командой pack(format, ...)), соответствующей строке формата format.

Строки формата

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

Порядок, размер и выравнивание байтов

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

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

Персонаж

Порядок байтов

Размер

Выравнивание

@

родной

родной

родной

=

родной

стандарт

нет

<

little-endian

стандарт

нет

>

big-endian

стандарт

нет

!

сеть (= big-endian)

стандарт

нет

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

Родной порядок байтов - big-endian или little-endian, в зависимости от хост-системы. Например, Intel x86 и AMD64 (x86-64) - little-endian; IBM z и большинство старых архитектур - big-endian; ARM, RISC-V и IBM Power имеют переключаемый порядок (bi-endian, хотя первые два почти всегда little-endian на практике). Используйте sys.byteorder, чтобы проверить конечность вашей системы.

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

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

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

Форма '!' представляет порядок байтов в сети, который всегда является big-endian, как определено в IETF RFC 1700.

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

Примечания:

  1. Вставка автоматически добавляется только между последовательными членами структуры. В начале и в конце закодированной структуры добавление вставки не производится.

  2. При использовании неродного размера и выравнивания, например, при использовании „<“, „>“, „=“ и „!“, вставка не добавляется.

  3. Чтобы выровнять конец структуры в соответствии с требованием выравнивания определенного типа, завершите формат кодом для этого типа с количеством повторений, равным нулю. См. Примеры.

Символы формата

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

Формат

C Тип

Тип Python

Стандартный размер

Примечания

x

байт блокнота

нет значения

c

char

байт длины 1

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[]

байты

p

char[]

байты

P

void*

целое число

(5)

Изменено в версии 3.3: Добавлена поддержка форматов 'n' и 'N'.

Изменено в версии 3.6: Добавлена поддержка формата 'e'.

Примечания:

  1. Код преобразования '?' соответствует типу _Bool, определенному в C99. Если этот тип недоступен, он моделируется с помощью char. В стандартном режиме он всегда представлен одним байтом.

  2. При попытке упаковать нецелое число с помощью любого из кодов преобразования целых чисел, если нецелое число имеет метод __index__(), то этот метод вызывается для преобразования аргумента в целое число перед упаковкой.

    Изменено в версии 3.2: Добавлено использование метода __index__() для нецелых чисел.

  3. Коды преобразования 'n' и 'N' доступны только для собственного размера (выбранного по умолчанию или с помощью символа порядка байтов '@'). Для стандартного размера вы можете использовать любой другой целочисленный формат, подходящий для вашего приложения.

  4. Для кодов преобразования 'f', 'd' и 'e' упакованное представление использует формат IEEE 754 binary32, binary64 или binary16 (для 'f', 'd' или 'e' соответственно), независимо от формата плавающей точки, используемого платформой.

  5. Символ формата 'P' доступен только для собственного упорядочения байтов (выбранного по умолчанию или с помощью символа порядка байтов '@'). Символ порядка байтов '=' выбирает использование little- или big-endian упорядочивания в зависимости от хост-системы. Модуль struct не интерпретирует это как собственное упорядочивание, поэтому формат 'P' недоступен.

  6. Тип IEEE 754 binary16 «половинной точности» был введен в ревизии 2008 года IEEE 754 standard. Он имеет знаковый бит, 5-битную экспоненту и 11-битную точность (с явным сохранением 10 бит), и может представлять числа между приблизительно 6.1e-05 и 6.5e+04 с полной точностью. Этот тип не очень широко поддерживается компиляторами языка Си: на типичной машине беззнаковое сокращение может использоваться для хранения, но не для математических операций. Дополнительную информацию см. на странице Википедии, посвященной half-precision floating-point format.

Символу формата может предшествовать интегральный счетчик повторов. Например, форматная строка '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: Ранее некоторые целочисленные форматы заворачивали значения, выходящие за пределы диапазона, и выдавали DeprecationWarning вместо struct.error.

Символ формата 'p' кодирует «строку Паскаля», то есть короткую строку переменной длины, хранящуюся в фиксированном количестве байт, задаваемом счетчиком. Первый сохраненный байт - это длина строки или 255, в зависимости от того, что меньше. Далее следуют байты строки. Если строка, переданная в pack(), слишком длинная (длиннее, чем счетчик минус 1), сохраняются только первые байты строки count-1. Если строка короче, чем count-1, она заполняется нулевыми байтами, так что всего используется ровно счетное количество байт. Обратите внимание, что для 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'

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

См.также

Модуль array

Упакованное двоичное хранение однородных данных.

Модуль xdrlib

Упаковка и распаковка данных XDR.

Занятия

Модуль 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.

Изменено в версии 3.7: Тип форматной строки теперь str вместо bytes.

size

Вычисленный размер struct (и, следовательно, байтового объекта, создаваемого методом pack()), соответствующего format.

Вернуться на верх