> **Источник:** https://python-all.ru/3.1/library/struct.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

# 7.3. `struct` – Интерпретация байтов как упакованных двоичных данных

Этот модуль выполняет преобразования между значениями Python и C-структурами, представленными в виде объектов Python [`bytes`](https://python-all.ru/3.1/library/functions.html#bytes). Его можно использовать для обработки двоичных данных, хранящихся в файлах или получаемых из сетевых соединений, а также других источников. Он использует [*строки форматирования*](https://python-all.ru/3.1/library/struct.html#struct-format-strings) как компактное описание структуры C-структур и предполагаемого преобразования в/из значений Python.

> **Примечание**
>
> По умолчанию результат упаковки заданной C-структуры включает байты заполнения для сохранения правильного выравнивания соответствующих типов C; аналогично, выравнивание учитывается при распаковке. Такое поведение выбрано для того, чтобы байты упакованной структуры точно соответствовали расположению в памяти соответствующей C-структуры. Для работы с платформонезависимыми форматами данных или для пропуска неявных байтов заполнения используйте *стандартный* размер и выравнивание вместо *собственного* размера и выравнивания: подробнее см. [*Порядок байтов, размер и выравнивание*](https://python-all.ru/3.1/library/struct.html#struct-alignment).

## 7.3.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*

. Результатом является кортеж, даже если он содержит ровно один элемент. Буфер должен содержать ровно столько данных, сколько требуется форматом (

`len(bytes)`

должно равняться

`calcsize(fmt)`

).

#### `struct.unpack_from(fmt, buffer, offset=0)`

Распаковывает из

*buffer*

, начиная с позиции

*offset*

, в соответствии со строкой форматирования

*fmt*

. Результатом является кортеж, даже если он содержит ровно один элемент.

*buffer*

должен содержать как минимум столько данных, сколько требуется форматом (

`len(buffer[offset:])`

должно быть не меньше

`calcsize(fmt)`

).

#### `struct.calcsize(fmt)`

Возвращает размер структуры (и, следовательно, объекта bytes, создаваемого

`pack(fmt, ...)`

), соответствующий строке форматирования

*fmt*

.

## 7.3.2. Строки формата

Строки формата – это механизм, используемый для указания ожидаемого расположения данных при упаковке и распаковке. Они составляются из [*символов формата*](https://python-all.ru/3.1/library/struct.html#format-characters), которые задают тип упаковываемых/распаковываемых данных. Кроме того, существуют специальные символы для управления [*порядком байтов, размером и выравниванием*](https://python-all.ru/3.1/library/struct.html#struct-alignment).

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

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

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

| Символ | Порядок байтов | Размер | Выравнивание |
| --- | --- | --- | --- |
| `@` | собственный | собственный | собственный |
| `=` | собственный | стандартный | нет |
| `<` | little-endian | стандартный | нет |
| `>` | big-endian | стандартный | нет |
| `!` | сетевой порядок байт (= big-endian) | стандартный | нет |

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

Собственный порядок байтов может быть big-endian или little-endian в зависимости от хост-системы. Например, Intel x86 и AMD64 (x86-64) используют little-endian; Motorola 68000 и PowerPC G5 – big-endian; ARM и Intel Itanium поддерживают переключаемый порядок байтов (bi-endian). Используйте `sys.byteorder` для проверки порядка байтов вашей системы.

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

Стандартный размер зависит только от символа формата; см. таблицу в разделе [*Символы формата*](https://python-all.ru/3.1/library/struct.html#format-characters).

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

Форма `'!'` доступна для тех несчастных, кто утверждает, что не может запомнить, является ли сетевой порядок байтов big-endian или little-endian.

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

Примечания:

1. Заполнение автоматически добавляется только между последовательными членами структуры. Начало и конец закодированной структуры не дополняются.
2. Заполнение не добавляется при использовании несобственного размера и выравнивания, например, с ‘\<’, ‘\>’, ‘=’ и ‘!’.
3. Чтобы выровнять конец структуры по требованию выравнивания конкретного типа, завершите формат кодом этого типа с нулевым количеством повторений. См. [*Примеры*](https://python-all.ru/3.1/library/struct.html#struct-examples).

### 7.3.2.2. Символы формата

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

| Формат | Тип C | Тип Python | Стандартный размер | Примечания |
| --- | --- | --- | --- | --- |
| `x` | байт заполнения | нет значения |  |  |
| `c` | `char` | строка байт длиной 1 | 1 |  |
| `b` | `знаковый char` | целое число | 1 | (1) |
| `B` | `unsigned char` | целое число | 1 |  |
| `?` | `_Bool` | bool | 1 | (2) |
| `h` | `short` | целое число | 2 |  |
| `H` | `unsigned short` | целое число | 2 |  |
| `i` | `int` | целое число | 4 |  |
| `I` | `unsigned int` | целое число | 4 |  |
| `l` | `long` | целое число | 4 |  |
| `L` | `unsigned long` | целое число | 4 |  |
| `q` | `long long` | целое число | 8 | (3) |
| `Q` | `unsigned long long` | целое число | 8 | (3) |
| `f` | `float` | float | 4 | (4) |
| `d` | `double` | float | 8 | (4) |
| `s` | `char[]` | байты |  | (1) |
| `p` | `char[]` | байты |  | (1) |
| `P` | `void *` | целое число |  | (5) |

Примечания:

1. Коды преобразования `c`, `s` и `p` работают с объектами [`bytes`](https://python-all.ru/3.1/library/functions.html#bytes), но упаковка с этими кодами также поддерживает объекты [`str`](https://python-all.ru/3.1/library/functions.html#str), которые кодируются с использованием UTF-8.
2. Код преобразования `'?'` соответствует типу `_Bool`, определённому в C99. Если этот тип недоступен, он имитируется с помощью `char`. В стандартном режиме он всегда представлен одним байтом.
3. Коды преобразования `'q'` и `'Q'` доступны в родном режиме, только если компилятор C платформы поддерживает C `long long` или, в Windows, `__int64`. Они всегда доступны в стандартных режимах.
4. Для кодов преобразования `'f'` и `'d'` упакованное представление использует формат IEEE 754 binary32 (для `'f'`) или binary64 (для `'d'`), независимо от формата чисел с плавающей запятой, используемого платформой.
5. Символ формата `'P'` доступен только для родного порядка байтов (выбранного по умолчанию или с помощью символа порядка байтов `'@'`). Символ порядка байтов `'='` выбирает порядок little- или big-endian в зависимости от хост-системы. Модуль struct не интерпретирует это как родной порядок, поэтому формат `'P'` недоступен.

Символу формата может предшествовать целочисленный счетчик повторений. Например, строка формата `'4h'` означает то же самое, что и `'hhhh'`.

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

Для символа формата `'s'` количество интерпретируется как длина строки в байтах, а не как количество повторений, как для других символов формата; например, `'10s'` означает одну строку длиной 10 байт, тогда как `'10c'` означает 10 символов. При упаковке строка усекается или дополняется нулевыми байтами по мере необходимости, чтобы соответствовать заданной длине. При распаковке результирующий объект bytes всегда содержит ровно указанное количество байт. В частном случае `'0s'` означает одну пустую строку (а `'0c'` означает 0 символов).

При упаковке значения `x` с использованием одного из целочисленных форматов (`'b'`, `'B'`, `'h'`, `'H'`, `'i'`, `'I'`, `'l'`, `'L'`, `'q'`, `'Q'`), если `x` выходит за допустимый диапазон для этого формата, то возбуждается [`struct.error`](https://python-all.ru/3.1/library/struct.html#struct.error).

Изменено в версии 3.1: В версии 3.0 некоторые целочисленные форматы обрабатывали значения, выходящие за пределы, и возбуждали [`DeprecationWarning`](https://python-all.ru/3.1/library/exceptions.html#DeprecationWarning) вместо [`struct.error`](https://python-all.ru/3.1/library/struct.html#struct.error).

Символ формата `'p'` кодирует «строку Паскаля», то есть короткую строку переменной длины, хранящуюся в *фиксированном количестве байтов*, заданном счетчиком. Первый сохраненный байт – это длина строки или 255, в зависимости от того, что меньше. Затем следуют байты строки. Если строка, переданная в [`pack()`](https://python-all.ru/3.1/library/struct.html#struct.pack), слишком длинная (длиннее, чем count минус 1), сохраняются только первые `count-1` байтов строки. Если строка короче `count-1`, она дополняется нулевыми байтами, так что всего используется ровно count байтов. Обратите внимание, что для [`unpack()`](https://python-all.ru/3.1/library/struct.html#struct.unpack) символ формата `'p'` потребляет `count` байтов, но возвращаемая строка никогда не может содержать более 255 байтов.

Для символа формата `'?'` возвращаемым значением является либо [`True`](https://python-all.ru/3.1/library/constants.html#True), либо [`False`](https://python-all.ru/3.1/library/constants.html#False). При упаковке используется истинностное значение объекта-аргумента. Будет упакован либо 0, либо 1 в нативном или стандартном представлении bool, а при распаковке любое ненулевое значение станет True.

### 7.3.2.3. Примеры

> **Примечание**
>
> Все примеры предполагают собственный порядок байтов, размер и выравнивание на машине с big-endian.

Простой пример упаковки/распаковки трёх целых чисел:

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

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

```python
>>> 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)
```

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

```python
>>> pack('ci', '*', 0x12131415)
b'*\x00\x00\x00\x12\x13\x14\x15'
>>> pack('ic', 0x12131415, '*')
b'\x12\x13\x14\x15*'
>>> calcsize('ci')
8
>>> calcsize('ic')
5
```

Следующий формат `'llh0l'` указывает два байта заполнения в конце, при условии, что значения long выровнены по границе 4 байта:

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

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

> **См. также**
>
> **Модуль [`array`](https://python-all.ru/3.1/library/array.html#module-array)**
>
> Упакованное бинарное хранение однородных данных.
>
> **Модуль [`xdrlib`](https://python-all.ru/3.1/library/xdrlib.html#module-xdrlib)**
>
> Упаковка и распаковка данных XDR.

## 7.3.3. Классы

Модуль `struct` также определяет следующий тип:

#### `class struct.Struct(format)`

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

Скомпилированные объекты Struct поддерживают следующие методы и атрибуты:

#### `pack(v1, v2, ...)`

Идентично функции

[`pack()`](https://python-all.ru/3.1/library/struct.html#struct.pack)

с использованием скомпилированного формата. (

`len(result)`

будет равно

`self.size`

.)

#### `pack_into(buffer, offset, v1, v2, ...)`

Идентично функции

[`pack_into()`](https://python-all.ru/3.1/library/struct.html#struct.pack_into)

с использованием скомпилированного формата.

#### `unpack(buffer)`

Идентично функции

[`unpack()`](https://python-all.ru/3.1/library/struct.html#struct.unpack)

с использованием скомпилированного формата. (

`len(buffer)`

должно быть равно

`self.size`

).

#### `unpack_from(buffer, offset=0)`

Идентично функции

[`unpack_from()`](https://python-all.ru/3.1/library/struct.html#struct.unpack_from)

с использованием скомпилированного формата. (

`len(buffer[offset:])`

должно быть не менее

`self.size`

).

#### `format`

Строка форматирования, используемая для создания этого объекта Struct.

#### `size`

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

[`pack()`](https://python-all.ru/3.1/library/struct.html#struct.pack)

) для

[`format`](https://python-all.ru/3.1/library/functions.html#format)

.
