Python. Модуль struct. Упаковка/распаковка данных. Базовые методы модуля

Модуль struct. Упаковка/распаковка данных. Базовые методы модуля


Содержание


Поиск на других ресурсах:




1. Использование модуля struct. Упакованные двоичные данные

Модуль struct в Python используется для создания и вытягивания упакованных двоичных данных из строк. В модуле struct байты данных интерпретируются как упакованные двоичные данные, которые могут быть представлены объектами типов bytes или bytearray.

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

Для обеспечения компактного описания C-структур и преобразования в значения (из значений) Python используются строки формата.

 

2. Базовые методы модуля struct

В модуле struct помещаются несколько базовых методов, которые можно использовать для упаковки и распаковки данных.

2.1. Методы pack() и unpack(). Упаковка и распаковка данных

Для упаковки и распаковки данных используются методы pack(), unpack(). Процесс упаковки/распаковывки реализуется в соответствии со строкой формата.

В соответствии с документацией, общая форма использования метода pack() следующая

obj = struct.pack(format, v1, v2, ...)

где

  • format – строка формата. Эта строка формируется в соответствии с правилами, которые заложены в таблицах (смотрите пункт 3);
  • v1, v2, … – значения (объекты), которые нужно упаковать;
  • obj – упакованный двоичный объект.

Функция unpack() выполняет обратные по отношению к pack() операции. Она позволяет получить исходный объект на основе упакованного объекта. Общая форма использования функции следующая:

obj = struct.unpack(format, buffer)

здесь

  • buffer – буфер, в котором записан объект, который был предварительно упакован функцией pack(). Размер этого объекта должен совпадать с размером, заданным в строке формата format;
  • format – строка формата на основе которой получается распакованный двоичный объект obj;
  • obj – результирующий объект, которым может быть список, кортеж, множество, словарь и т.п.

При вызове функции unpack() строка формата должна совпадать с такой же строкой, которая была задана функцией pack().

Пример. С целью демонстрации осуществляется упаковка/распаковка списка чисел.

# Модуль struct. Методы pack(), unpack()
# Упаковать/распаковать список чисел

# 1. Заданный список чисел
LS = [ 1, 3, 9, 12 ]

# 2. Подключить модуль struct
import struct

# 3. Упаковать список чисел. Метод pack()
pack_obj = struct.pack('>4і', LS[0], LS[1], LS[2], LS[3])

# 4. Вывести упакованный объект pack_obj
print('pack_obj = ', pack_obj)

# 5. Распаковать список чисел. Метод unpack().
#   Результатом есть кортеж T2
T2 = struct.unpack('>4і', pack_obj) # T2 = (1, 3, 9, 12)

# 6. Вывести распакованный объект T2
print('T2 = ', T2)

# 7. Конвертировать кортеж T2 в список LS2
LS2 = list(T2) # LS2 =   [1, 3, 9, 12]

# 8. Вывести список LS2
print('LS2 = ', LS2)

Результат работы программы

pack_obj =   b'\x00\x00\x00\x01\x00\x00\x00\x03\x00\x00\x00\t\x00\x00\x00\x0c'
T2 = (1, 3, 9, 12)
LS2 = [1, 3, 9, 12]

 

2.2. Метод calcsize(). Размер упакованного объекта

Метод calcsize() возвращает размер объекта, созданного методом pack().

Пример.

# Модуль struct.
# Метод calcsize(). Определить размер упакованного объекта

# 1. Подключить модуль struct
import struct

# 2. Определить размер упакованного списка чисел
# 2.1. Заданный список вещественных чисел
LS = [ 2.88, 3.9, -10.5 ]

# 2.2. Упаковать список LS. Метод pack()
pack_obj = struct.pack('>3f', LS[0], LS[1], LS[2])

# 2.3. Вывести упакованный объект pack_obj
print('pack_obj = ', pack_obj)

# 2.4. Вывести размер объекта pack_obj
size = struct.calcsize('>3f') # size = 12
print('size = ', size)

# 3. Определить размер упакованного кортежа строк
# 3.1. Заданный кортеж из двух строк
TS = ( 'Hello', 'abcd')

# 3.2. Упаковать кортеж TS
pack_obj = struct.pack('<5s4s', TS[0].encode(), TS[1].encode())

# 3.3. Вывести упакованный объект
print('pack_obj = ', pack_obj)

# 3.4. Вывести размер упакованного кортежа
size = struct.calcsize('<5s4s') # size = 9
print('size = ', size)

Результат выполнения программы

pack_obj = b'@8Q\xec@y\x99\x9a\xc1(\x00\x00'
size = 12
pack_obj = b'Helloabcd'
size = 9

 

3. Форматированные строки
3.1. Установка порядка байт, размера и выравнивания на основании символа формата

В языке Python способ упаковки строки определяется на основе первого символа строки формата. Этот символ определяет:

  • порядок байт, который формируется с помощью символов @, =, <, >, !. Если не указать этого параметра, то принимается символ @;
  • размер в байтах упакованных данных. В этом случае первыми используются цифры, которые обозначают число;
  • выравнивание, устанавливаемое системой.

В соответствии с документацией Python в строке формата порядок байт, размер и выравнивание формируются согласно первому символу формата. Возможные первые символы формата отображены в следующей таблице.

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

Значение порядка байт может быть одним из 4-х:

  • естественной порядок (native). Этот порядок может быть или little-endian или big-endian. Данный порядок определяется в зависимости от хост-системы;
  • порядок типа little-endian. При таком порядке первым обрабатывается младший байт, а затем уже старший байт;
  • порядок типа big-endian. В этом случае первым обрабатывается старший байт, а затем уже младший байт;
  • сетевой порядок (network), который по умолчанию равен порядку big-endian.

Размер упакованных данных может быть одним из двух:

  • естественный – определяется с помощью инструкции sizeof компилятора языка C;
  • стандартный – определяется на основе символа формата в соответствии с нижеследующей таблицей.

Таблица. Определение стандартного размера упакованных данных в зависимости от символа формата

Формат Тип в языке C Тип в языке Python Стандартный размер
x pad byte без значения
c char байты длиной 1 1
b signed char integer 1
B unsigned char integer 1
? _Bool bool 1
h short integer 2
H unsigned short integer 2
i int integer 4
I unsigned int integer 4
l long integer 4
L unsigned long integer 4
q long long integer 8
Q unsigned long long integer 8
n ssize_t integer
N size_t integer
e float (экспоненциальный формат) float 2
f float float 4
d double float 8
s char[] bytes
p char[] bytes
P void* integer

 

3.2. Примеры форматированных строк для разных типов данных

 

ii   - два числа типа int
2i   - два числа типа int
10f  - 10 чисел типа float
>i8s - порядок байт big-endian, число типа int, строка из 8 символов
8dif - 8 чисел типа double, 1 число типа int, 1 число типа float
=bi   - естественной порядок, значение типа bool, число типа int

 


Связанные темы