Spec-Zone.ru › Python 3.13

struct — интерпретация байтов как упакованных двоичных данных

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

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

Примечание

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

Некоторые функции 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). Такое поведение выбрано для того, чтобы байты упакованной структуры точно соответствовали расположению в памяти соответствующей структуры 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.

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

Примечания:

  1. Заполнение автоматически добавляется только между последовательными элементами структуры. В начале или конце закодированной структуры заполнение не добавляется.
  2. При использовании нестандартных размера и выравнивания, например с ‘<’, ‘>’, ‘=’ и ‘!’, заполнение не добавляется.
  3. Чтобы выровнять конец структуры согласно требованиям к выравниванию определённого типа, завершите формат кодом этого типа с нулевым числом повторений. См. раздел Примеры.

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

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

Формат

Тип C

Тип Python

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

Примечания

x

байт-заполнитель

нет значения

(7)

c

char

bytes длиной 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)

число с плавающей точкой

2

(4)

f

float

число с плавающей точкой

4

(4)

d

double

число с плавающей точкой

8

(4)

s

char[]

bytes

(9)

p

char[]

bytes

(8)

P

void*

целое число

(5)

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

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

Примечания:

  1. Код преобразования '?' соответствует типу _Bool, определённому стандартами C начиная с C99. В стандартном режиме он представлен одним байтом.
  2. При попытке упаковать нецелое значение с помощью любого кода преобразования целых чисел, если у этого значения есть метод __index__(), этот метод вызывается для преобразования аргумента в целое число перед упаковкой.

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

  3. Коды преобразования 'n' и 'N' доступны только для собственного размера (выбирается по умолчанию или с помощью символа порядка байтов '@'). Для стандартного размера можно использовать любой из других целочисленных форматов, подходящий для вашего приложения.
  4. Для кодов преобразования 'f', 'd' и 'e' упакованное представление использует формат IEEE 754 binary32, binary64 или binary16 (соответственно для 'f', 'd' или 'e') независимо от формата чисел с плавающей точкой, используемого платформой.
  5. Символ формата 'P' доступен только для собственного порядка байтов (выбирается по умолчанию или с помощью символа порядка байтов '@'). Символ порядка байтов '=' выбирает порядок little-endian или big-endian в зависимости от хост-системы. Модуль struct не рассматривает его как собственный порядок, поэтому формат 'P' недоступен.
  6. Тип IEEE 754 binary16 «половинной точности» появился в редакции 2008 года стандарта IEEE 754. Он содержит бит знака, 5-битную экспоненту и 11 бит точности (из которых 10 бит хранятся явно) и может представлять числа в диапазоне примерно от 6.1e-05 до 6.5e+04 с полной точностью. Этот тип широко не поддерживается компиляторами C: на типичной машине для хранения можно использовать unsigned short, но не для математических операций. Дополнительные сведения см. на странице Википедии о формате чисел с плавающей точкой половинной точности.
  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 или обратно. (Конкретный пример этого различия см. в разделе Примеры.) Если счётчик не указан, по умолчанию он равен 1. При упаковке строка при необходимости усекается или дополняется нулевыми байтами, чтобы соответствовать заданной длине. При распаковке результирующий объект bytes всегда содержит ровно указанное количество байтов. В частном случае '0s' означает одну пустую строку (тогда как '0c' означает 0 символов).

Перед символом формата можно указать целое число повторений. Например, строка формата '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.

Примеры

Примечание

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

Упаковка и распаковка целых чисел трёх разных размеров с использованием порядка 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 ниже после упакованного значения '#' добавлены три нулевых байта, чтобы выровнять следующее целое число по границе четырёх байтов. В этом примере вывод получен на машине с порядком little-endian:

>>> 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' приводит к добавлению двух байтов-заполнителей в конце, если длинные целые числа на платформе выровнены по границам четырёх байтов:

>>> pack('@llh0l', 1, 2, 3)
b'\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00'

См. также

Module array

Компактное двоичное хранение однородных данных.

Module json

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

Module pickle

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

Применение

Модуль struct предназначен для двух основных задач: обмена данными между Python и кодом C в рамках одного приложения или другого приложения, скомпилированного тем же компилятором (собственные форматы), и обмена данными между приложениями с согласованным расположением данных (стандартные форматы). Как правило, строки формата для этих двух областей различаются.

Собственные форматы

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

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

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

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

>>> calcsize('@llh0l')
24

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

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

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

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

Классы

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

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

size

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

Изменено в версии 3.13: Представление repr() структур изменилось. Теперь оно выглядит так:

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

© 2001–2025 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.13/library/struct.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API