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 появились более информативные сообщения об ошибках для некорректных буферов.
Расширенные примеры использования
# Обработка бинарных структур
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
# Использование итератора 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)
# Работа с переменными строками
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