# struct

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

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

{% hint style="info" %}
По умолчанию результат упаковки данной структуры C включает байты заполнения, чтобы поддерживать правильное выравнивание для задействованных типов C; аналогично при распаковке учитывается соосность. Это поведение выбрано таким образом, чтобы байты упакованной структуры точно соответствовали разметке в памяти соответствующей структуры C. Чтобы обрабатывать независимые от платформы форматы данных или опускать неявные байты заполнения, используйте стандартный размер `standard` и выравнивание вместо собственного размера `native` и выравнивания: подробности см. в разделе **Порядок байтов, размер и выравнивание**.
{% endhint %}

Некоторые функции **struct** (и методы Struct) принимают аргумент буфера ***buffer***. Это относится к объектам, которые реализуют протокол буфера и предоставляют буфер с возможностью чтения или записи и чтения. Наиболее распространенными типами, используемыми для этой цели, являются байты ***bytes*** и байтовый массив ***bytearray***, но многие другие типы, которые можно рассматривать как массив байтов, реализуют протокол буфера, так что их можно читать/заполнять без дополнительного копирования из байтового объекта.

### Функции и исключения

Модуль определяет следующие исключения и функции:

* struct.error exception
* [struct.pack ()](https://treasuremaster.gitbook.io/python-docs/moduli-standartnoi-biblioteki-1/dvoichnye-dannye/struct/struct.pack) - возвращает байтовый объект с упакованными в заданном формате данными
* struct.pack\_into ()
* [struct.unpack ()](https://treasuremaster.gitbook.io/python-docs/moduli-standartnoi-biblioteki-1/dvoichnye-dannye/struct/struct.unpack) - распаковывает упакованный байтовый объект и возвращает кортеж
* struct.unpack\_from ()
* struct.iter\_unpack ()
* struct.calcsize ()

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

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

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

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

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

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

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

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

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

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

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

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

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

{% hint style="info" %}

1. Заполнение автоматически добавляется только между последовательными членами структуры. В начале или в конце закодированной структуры заполнение не добавляется.
2. При использовании нестандартного размера и выравнивания отступы не добавляются, например с помощью `'<'`, `'>'`, `'='` и `'!'`.
3. Чтобы выровнять конец структуры по требованию выравнивания определенного типа, завершите формат кодом для этого типа с нулевым счетчиком повторов. См. примеры.
   {% endhint %}

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

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

| Формат  | Тип С              | Тип Python      | Стандартный размер | Примечание |
| ------- | ------------------ | --------------- | ------------------ | ---------- |
| **x**   | pad byte           | нет значения    |                    |            |
| **c**   | char               | байт с длиной 1 | 1                  |            |
| **b**   | signed char        | integer         | 1                  | (1), (2)   |
| **B**   | unsigned byte      | 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**   | size\_t            | integer         |                    | (3)        |
| **N**   | size\_t            | integer         |                    | (3)        |
| **e**   | (6)                | float           | 2                  | (4)        |
| **f**   | float              | float           | 4                  | (4)        |
| **d**   | double             | float           | 8                  | (4)        |
| **s**   | char \[ ]          | bytes           |                    |            |
| **p**   | char \[ ]          | bytes           |                    |            |
| **P**   | void \*            | integer         |                    | (5)        |

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

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

{% hint style="info" %}

1. Код преобразования `'?'` соответствует типу **\_Bool**, определенному в C99. Если этот тип недоступен, он моделируется с помощью символа **char**. В стандартном режиме он всегда представлен одним байтом.
2. При попытке упаковать нецелое число с использованием любого из кодов преобразования целого числа, если нецелое число имеет метод `'__index__` ` ``()'`, то этот метод вызывается для преобразования аргумента в целое число перед упаковкой. *Изменено в версии 3.2:* использование метода `'__index__  ()'` для нецелых чисел является новым в версии 3.2.
3. Коды преобразования `'n'` и `'N'` доступны только для исходного размера (выбранного по умолчанию или с помощью символа порядка байтов `'@'`). Для стандартного размера вы можете использовать любой другой целочисленный формат, подходящий для вашего приложения.
4. Для кодов преобразования `'f'`, `'d'` и `'e'` упакованное представление использует формат IEEE 754 binary32, binary64 или binary16 (для `'f'`, `'d'` или `'e'` соответственно), независимо от числа с плавающей точкой, используемого платформой.
5. Символ формата `'P'` доступен только для собственного порядка байтов (выбран по умолчанию или с помощью символа порядка байтов `'@'`). Символ порядка байтов `'='` выбирает использование прямого или обратного порядка байтов в зависимости от хост-системы. Модуль **struct** не интерпретирует это как собственный порядок, поэтому формат `'P'` недоступен.
6. Тип «половинной точности» IEEE 754 binary16 был введен в редакцию 2008 года стандарта [IEEE 754](https://en.wikipedia.org/wiki/IEEE_754#IEEE_754-2008). Он имеет знаковый бит, 5-битную экспоненту и 11-битную точность (с явно сохраненными 10 битами) и может представлять числа от примерно `6.1e-05` до `6.5e+04` с полной точностью. Этот тип широко не поддерживается компиляторами C: на типичной машине беззнаковое сокращение может использоваться для хранения, но не для математических операций. См. страницу Википедии о [формате с плавающей запятой половинной точности](https://en.wikipedia.org/wiki/Half-precision_floating-point_format) для получения дополнительной информации.
   {% endhint %}

Символу формата может предшествовать целое число повторов. Например, строка формата `'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](https://treasuremaster.gitbook.io/python-docs/moduli-standartnoi-biblioteki-1/dvoichnye-dannye/struct/struct.error).

*Изменено в версии 3.1:* в версии 3.0 некоторые целочисленные форматы переносили значения, выходящие за пределы допустимого диапазона, и вызывали **DeprecationWarning** вместо [struct.error](https://treasuremaster.gitbook.io/python-docs/moduli-standartnoi-biblioteki-1/dvoichnye-dannye/struct/struct.error).

Символ формата `'p'` кодирует «*Pascal string*», означающую короткую строку переменной длины, хранящуюся в фиксированном количестве байтов, определяемом счетчиком. Первый сохраненный байт - это длина строки или 255, в зависимости от того, что меньше. Далее следуют байты строки. Если строка, переданная в [pack ()](https://treasuremaster.gitbook.io/python-docs/moduli-standartnoi-biblioteki-1/dvoichnye-dannye/struct/struct.pack), слишком длинная (длиннее, чем `count - 1`), сохраняются только ведущие байты `count - 1` строки. Если строка короче, чем `count - 1`, она дополняется нулевыми байтами, чтобы использовалось ровно count байтов во всех. Обратите внимание, что для [unpack ()](https://treasuremaster.gitbook.io/python-docs/moduli-standartnoi-biblioteki-1/dvoichnye-dannye/struct/struct.unpack) символ формата `'p'` потребляет количество байтов, но возвращаемая строка никогда не может содержать больше 255 байтов.

Для символ формата `'?'`, возвращаемое значение - `True` или `False`. При упаковке используется истинное значение объекта аргумента. Либо 0, либо 1 в собственном или стандартном представлении ***bool*** будут упакованы, и любое ненулевое значение будет `True` при распаковке.

### Примеры

{% hint style="info" %}
Все примеры предполагают собственный ***native*** порядок байтов, размер и выравнивание с машиной с прямым (*big-endian*) порядком байтов.
{% endhint %}

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

```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', 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-байтовым границам:

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

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

{% hint style="info" %}
Смотрите также:

* модуль [array](https://treasuremaster.gitbook.io/python-docs/moduli-standartnoi-biblioteki-1/specialnye-tipy-dannykh/array) - упакованное двоичное хранилище однородных данных.
* модуль [xdrlib](https://treasuremaster.gitbook.io/python-docs/moduli-standartnoi-biblioteki-1/formaty-failov/xdrlib) - упаковка и распаковка данных XDR
  {% endhint %}

### Классы

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

* struct.Struct class

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

* pack ()
* pack\_into ()
* unpack ()
* unpack\_from ()
* iter\_unpack ()
* format
* size
