Struct.unpack: примеры (PYTHON)

Работа с двоичными данными через struct.unpack в Python
Раздел: Бинарные данные, Распаковка
struct.unpack(fmt: str, buffer: bytes): tuple

Основы функции struct.unpack

Функция struct.unpack() из модуля struct используется для преобразования упакованных двоичных данных в кортеж Python, согласно заданному формату. Она обратна функции struct.pack() и применяется при чтении двоичных файлов, работе с сетевыми протоколами, взаимодействии с оборудованием и системными вызовами.

Сигнатура функции: struct.unpack(format, buffer)

Параметры:

  • format - строка, определяющая расположение и типы данных. Состоит из символов формата (например, 'i' для целого числа, 'f' для float) и необязательных префиксов порядка байтов (@, =, <, >, !).
  • buffer - объект, поддерживающий протокол буфера (bytes, bytearray, memoryview), содержащий упакованные данные.

Возвращаемое значение: кортеж Python с распакованными значениями. Если буфер содержит несколько элементов согласно формату, все они возвращаются в кортеже. Размер буфера должен точно соответствовать размеру, требуемому форматом.

Базовые примеры использования

import struct

# Распаковка одного целого числа
packed_data = struct.pack('i', 42)
result = struct.unpack('i', packed_data)
print(result)
(42,)
# Несколько значений разных типов
packed = struct.pack('i f 4s', 10, 3.14, b'test')
values = struct.unpack('i f 4s', packed)
print(values)
(10, 3.140000104904175, b'test')
# Указание порядка байтов
big_endian = struct.pack('>i', 1000)
little_endian = struct.pack('<i', 1000)
print(struct.unpack('>i', big_endian))
print(struct.unpack('<i', little_endian))
(1000,)
(1000,)

Альтернативные подходы в Python

struct.pack() - функция для упаковки данных в байты, обратная к unpack. Используется, когда нужно преобразовать Python-объекты в двоичный формат.

array.array - модуль для работы с массивами примитивных типов. Эффективен для обработки больших однородных данных.

memoryview - предоставляет доступ к внутренним данным буфера без копирования. Полезен при работе с крупными массивами байтов.

ctypes - позволяет создавать C-совместимые типы данных и работать с разделяемыми библиотеками. Подходит для низкоуровневого взаимодействия.

pickle - модуль для сериализации Python-объектов. Используется для сохранения состояния объектов, но не для межъязыкового обмена.

Аналоги в других языках программирования

PHP: функция unpack()

$data = unpack('iint', hex2bin('2a000000'));
print_r($data);
Array
(
    [int] => 42
)

JavaScript (Node.js): Buffer

const buf = Buffer.from([0x2a, 0x00, 0x00, 0x00]);
const result = buf.readInt32LE(0);
console.log(result);
42

Java: ByteBuffer

ByteBuffer buffer = ByteBuffer.wrap(new byte[]{0x2a, 0, 0, 0});
buffer.order(ByteOrder.LITTLE_ENDIAN);
int value = buffer.getInt();
System.out.println(value);
42

C#: класс BitConverter

byte[] bytes = {0x2a, 0x00, 0x00, 0x00};
int value = BitConverter.ToInt32(bytes, 0);
Console.WriteLine(value);
42

Распространенные ошибки

# Несоответствие размера буфера
import struct
try:
    struct.unpack('i', b'\x01\x02\x03')
except struct.error as e:
    print(f'Ошибка: {e}')
Ошибка: unpack requires a buffer of 4 bytes
# Неверный формат строки
try:
    struct.unpack('x', b'\x01')
except struct.error as e:
    print(f'Ошибка: {e}')
Ошибка: bad char in struct format
# Неправильный порядок байтов
packed = struct.pack('<i', 1000)
try:
    struct.unpack('>i', packed)
except:
    print('Получено некорректное значение')
Получено некорректное значение

Изменения в последних версиях Python

В Python 3.11 добавлена поддержка формата 'n' для размеров типа ssize_t. С версии 3.6 форматные строки могут быть экземплярами bytes. Python 3.7 улучшил обработку ошибок при неверных форматах. В версии 3.10 появились более информативные сообщения об ошибках для некорректных буферов.

Расширенные примеры использования

Пример python
# Обработка бинарных структур
import struct

# Работа с заголовком файла BMP
bmp_header = b'BM' + struct.pack('<iHHHI', 1024, 0, 0, 54, 40)
signature, file_size, _, _, offset, header_size = \
    struct.unpack('<2sIHHII', bmp_header[:26])
print(f'Сигнатура: {signature}')
print(f'Размер файла: {file_size}')
Сигнатура: b'BM'
Размер файла: 1024
Пример python
# Использование итератора unpack
from struct import iter_unpack

# Обработка массива координат
coords = struct.pack('6f', 1.0, 2.0, 3.0, 4.0, 5.0, 6.0)
for point in iter_unpack('3f', coords):
    print(f'Точка: {point}')
Точка: (1.0, 2.0, 3.0)
Точка: (4.0, 5.0, 6.0)
Пример python
# Работа с переменными строками
import struct

# Формат с переменной длиной строки
data = struct.pack('i5s', 10, b'hello')
value, text = struct.unpack('i5s', data)
text = text.decode('utf-8').rstrip('\x00')
print(f'Число: {value}, Текст: {text}')
Число: 10, Текст: hello

питон struct.unpack function comments

En
Struct.unpack Unpack from a buffer according to a format string