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('>4i', LS[0], LS[1], LS[2], LS[3])

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

# 5. Розпакувати список чисел. Метод unpack().
#    Результатом є кортеж T2
T2 = struct.unpack('>4i', 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

 


Зв’язані теми