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

Kod źródłowy: Lib/struct.py


Этот модуль преобразует значения Python в структуры C, представленные как объекты Python bytes. Компактные строки формата <struct-format-strings>` описывают предполагаемые преобразования в/из значений Python. Функции и объекты модуля могут использоваться для двух совершенно разных приложений: обмена данными с внешними источниками (файлами или сетевыми подключениями) или передачи данных между приложением Python и уровнем C.

Informacja

Если префикс не указан, по умолчанию используется собственный режим. Он упаковывает или распаковывает данные на основе платформы и компилятора, на которых был построен интерпретатор Python. Результат упаковки данной структуры C включает байты заполнения, которые поддерживают правильное выравнивание для задействованных типов C; аналогично выравнивание учитывается при распаковке. Напротив, при передаче данных между внешними источниками программист отвечает за определение порядка байтов и заполнение между элементами. Подробности смотрите в Порядок байтів, розмір і вирівнювання.

Кілька функцій struct (та методи Struct) приймають аргумент buffer. Це відноситься до об’єктів, які реалізують Buffer Protocol і забезпечують доступний для читання чи запису буфер. Найпоширенішими типами, які використовуються для цієї мети, є 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().

Кожна ітерація дає кортеж, як зазначено в рядку формату.

Dodane w wersji 3.4.

struct.calcsize(format)

Повертає розмір структури (і, отже, об’єкта bytes, створеного pack(format, ...)), що відповідає рядку формату format.

Форматувати рядки

Строки формата описывают расположение данных при упаковке и распаковке данных. Они состоят из formatcharacters, которые определяют тип упаковываемых/распаковываемых данных. Кроме того, специальные символы управляют порядком байтов, размером и выравниванием<struct-alignment>`. Каждая строка формата состоит из необязательного префиксного символа, который описывает общие свойства данных, и одного или нескольких символов формата, которые описывают фактические значения данных и заполнение.

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

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

Крім того, перший символ рядка формату можна використовувати для вказівки порядку байтів, розміру та вирівнювання упакованих даних згідно з наведеною нижче таблицею:

Znak

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

Розмір

Вирівнювання

@

рідний

рідний

рідний

=

рідний

стандарт

немає

<

маленький байт

стандарт

немає

>

великий байт

стандарт

немає

!

мережа (= порядок байтів)

стандарт

немає

Якщо перший символ не є одним із цих, передбачається '@'.

Informacja

Число 1023 (шестнадцатеричное 0x3ff) имеет следующие байтовые представления:

  • 03 ff in big-endian (>)

  • ff 03 in little-endian (<)

Пример Python:

>>> import struct
>>> struct.pack('>h', 1023)
b'\x03\xff'
>>> struct.pack('<h', 1023)
b'\xff\x03'

Собственный порядок байтов — прямой или прямой, в зависимости от хост-системы. Например, Intel x86, AMD64 (x86-64) и Apple M1 имеют прямой порядок байтов; IBM z и многие устаревшие архитектуры имеют обратный порядок байтов. Используйте sys.byteorder, чтобы проверить порядок байтов вашей системы.

Власний розмір і вирівнювання визначаються за допомогою виразу sizeof компілятора C. Це завжди поєднується з рідним порядком байтів.

Стандартний розмір залежить тільки від символу формату; див. таблицю в розділі Format Characters.

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

Форма '!' представляє мережевий порядок байтів, який завжди є старшим байтом, як визначено в IETF RFC 1700.

Немає способу вказати невласний порядок байтів (примусова заміна байтів); використовуйте відповідний вибір ' <' or '> ''.

Uwagi:

  1. Відступи автоматично додаються лише між послідовними елементами структури. Заповнення не додається на початку або в кінці закодованої структури.

  2. Під час використання невласного розміру та вирівнювання відступи не додаються, напр. з „<», «>”, „=” і „!”.

  3. Щоб вирівняти кінець структури відповідно до вимог вирівнювання певного типу, завершіть формат кодом для цього типу з нульовою кількістю повторів. Див. Przykłady.

Format Characters

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

Format

typ języka C

Python type

Стандартний розмір

Notatki

x

pad byte

немає значення

(7)

c

char

байти довжиною 1

1

b

signed char

integer

1

(1), (2)

B

unsigned char

integer

1

(2)

?

_Bool

bool

1

(1)

h

short

integer

2

(2)

H

unsigned short

integer

2

(2)

i

int

integer

4

(2)

I

unsigned int

integer

4

(2)

l

long

integer

4

(2)

L

unsigned long

integer

4

(2)

q

long long

integer

8

(2)

Q

unsigned long long

integer

8

(2)

n

ssize_t

integer

(3)

N

size_t

integer

(3)

e

(6)

typ (float) zmiennoprzecinkowy pojedynczej precyzji

2

(4)

f

float

typ (float) zmiennoprzecinkowy pojedynczej precyzji

4

(4)

d

double

typ (float) zmiennoprzecinkowy pojedynczej precyzji

8

(4)

s

char[]

bytes

(9)

p

char[]

bytes

(8)

P

void*

integer

(5)

Zmienione w wersji 3.3: Додано підтримку форматів 'n' і 'N'.

Zmienione w wersji 3.6: Додано підтримку формату 'e''.

Uwagi:

  1. Код преобразования '?' соответствует типу _Bool, определенному стандартами C, начиная с C99. В стандартном режиме он представлен одним байтом.

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

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

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

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

  5. Символ формату 'P' доступний лише для власного порядку байтів (вибрано як типовий або з символом порядку байтів '@'). Символ порядку байтів '=' вибирає порядок використання малого або великого порядку байтів на основі головної системи. Модуль struct не інтерпретує це як рідне впорядкування, тому формат 'P' недоступний.

  6. Двійковий тип16 IEEE 754 із „половиною точності” було введено в редакції 2008 року стандарту IEEE 754. Він має знаковий біт, 5-бітний експоненту та 11-бітну точність (з 10 бітами, збереженими явно), і може представляти числа приблизно від 6.1e-05 до 6.5e+04 з повною точністю. . Цей тип не широко підтримується компіляторами C: на типовій машині беззнаковий короткий можна використовувати для зберігання, але не для математичних операцій. Перегляньте сторінку Вікіпедії про формат числа з плаваючою комою половинної точності для отримання додаткової інформації.

  7. При упаковке 'x' вставляет один NUL-байт.

  8. Символ формату 'p' кодує „рядок Pascal”, що означає короткий рядок змінної довжини, що зберігається у фіксованій кількості байтів, визначеній підрахунком. Перший збережений байт — це довжина рядка або 255, залежно від того, що менше. Далі йдуть байти рядка. Якщо рядок, переданий у pack(), задовгий (довший за лічильник мінус 1), зберігаються лише перші байти count-1 рядка. Якщо рядок коротший за count-1, він доповнюється нульовими байтами, щоб використати рівно кількість байтів. Зверніть увагу, що для unpack() символ формату 'p' споживає count байтів, але що повернутий рядок ніколи не може містити більше 255 байтів.

  9. Для символа формата 's' счетчик интерпретируется как длина байтов, а не как счетчик повторений, как для других символов формата; например, '10s' означает одну 10-байтовую строку, сопоставленную с одной байтовой строкой Python или из нее, а '10c' означает 10 отдельных однобайтовых символьных элементов (например, cccccccccc ) сопоставление десяти различным байтовым объектам Python или обратно. (См. Przykłady для конкретной демонстрации разницы.) Если счетчик не указан, по умолчанию он равен 1. Для упаковки строка усекается или дополняется нулевыми байтами, чтобы она соответствовала размеру. При распаковке результирующий объект байтов всегда содержит ровно указанное количество байтов. В частном случае '0s' означает одну пустую строку (в то время как '0c' означает 0 символов).

Символу форматування може передувати цілий підрахунок повторів. Наприклад, рядок формату '4h'' означає те саме, що 'hhhh'.

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

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

Zmienione w wersji 3.1: Раніше деякі цілочисельні формати обгортали значення поза діапазоном і викликали DeprecationWarning замість struct.error.

Для символу формату '?' повертається значення True або False. При упаковці використовується значення істинності об’єкта аргументу. Буде запаковано 0 або 1 у нативному або стандартному логічному представленні, а будь-яке ненульове значення під час розпакування буде True.

Przykłady

Informacja

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

Упаковывайте и распаковывайте целые числа трёх разных размеров, используя обратный порядок байтов:

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

Попытка упаковать целое число, которое слишком велико для определенного поля:

>>> пакет(">h", 99999) Traceback (последний вызов последний): Файл «<stdin>», строка 1, в <модуле> struct.error: для формата 'h' требуется -32768 <= число <= 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 ниже, после упакованного '#' были добавлены три NUL-байта, чтобы выровнять следующее целое число по границе четырех байтов. В этом примере выходные данные были созданы на машине с прямым порядком байтов:

>>> 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'

Zobacz także

Модуль array

Упаковане двійкове сховище однорідних даних.

moduł json

Кодер и декодер JSON.

moduł pickle

Сериализация объектов Python.

Приложения

Существуют два основных приложения для модуля struct: обмен данными между кодом Python и C внутри приложения или другого приложения, скомпилированного с использованием одного и того же компилятора (native formats) и обмен данными между приложениями с использованием согласованного формата данных (standard formats). Вообще говоря, строки формата, созданные для этих двух доменов, различны.

Родные форматы

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

Рассмотрим эти два простых примера (на 64-битной машине с прямым порядком байтов):

>>> calcsize('@lhl')
24
>>> calcsize('@llh')
18

Данные не дополняются до 8-байтовой границы в конце второй строки формата без использования дополнительного заполнения. Код формата с нулевым повторением решает эту проблему:

>>> calcsize('@llh0l')
24

Код формата 'x' может использоваться для указания повторения, но для собственных форматов лучше использовать формат с нулевым повторением, например '0l'.

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

Стандартные форматы

При обмене данными, выходящим за рамки вашего процесса, например, сети или хранилища, будьте точны. Укажите точный порядок байтов, размер и выравнивание. Не думайте, что они соответствуют исходному порядку конкретной машины. Например, порядок байтов в сети — обратный порядок байтов, тогда как у многих популярных процессоров — прямой порядок байтов. Определив это явно, пользователю не нужно беспокоиться о специфике платформы, на которой работает его код. Первым символом обычно должен быть < или > (или !). Заполнение является обязанностью программиста. Символ формата с нулевым повтором не будет работать. Вместо этого пользователь должен явно добавить 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

Klasy

Модуль struct також визначає наступний тип:

class struct.Struct(format)

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

Informacja

Скомпилированные версии самых последних строк формата, переданных функциям уровня модуля, кэшируются, поэтому программам, которые используют только несколько строк формата, не нужно беспокоиться о повторном использовании одного экземпляра 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.

Dodane w wersji 3.4.

format

Рядок формату, який використовується для створення цього об’єкта Struct.

Zmienione w wersji 3.7: Тип рядка формату тепер str замість bytes.

size

Розрахований розмір структури (і, отже, об’єкта bytes, створеного методом pack()), що відповідає format.

Zmienione w wersji 3.13: repr() структур изменился. Это сейчас:

>>> Struct('i')
Struct('i')