struct модуль у Python
The struct модуль в Python дозволяє працювати з двійковими даними, надаючи функціональні можливості для перетворення між значеннями Python і двійковими даними у стилі C. Це особливо корисно під час роботи з двійковими форматами файлів або мережевими протоколами. Його ключові особливості включають:
- Упаковка конвертувати значення Python у двійкові дані (байти).
- Розпакування конвертувати двійкові дані назад у значення Python.
- Форматувати рядки визначте, як дані упаковуються/розпаковуються за допомогою кодів формату (наприклад, i для цілих чисел f для числа з плаваючою точкою).
Методи в struct.pack()
1.Struct.pack(): Він перетворює значення Python у упакований двійковий формат. Рядок формату (fmt) визначає макет упакованих даних, а наступні значення (v1 v2 ...) упаковуються відповідно до цього формату. Синтаксис:
struct.pack(fmt v1 v2 ...)
- fmt : Рядок формату, який визначає спосіб упаковки даних.
- v1 v2 ...: Значення, які будуть упаковані відповідно до вказаного формату.
import struct # pack values into binary var = struct . pack ( 'hhl' 1 2 3 ) print ( var ) var = struct . pack ( 'iii' 1 2 3 ) print ( var )
Вихід
b'x01x00x02x00x00x00x00x00x03x00x00x00x00x00x00x00' b'x01x00x00x00x02x00x00x00x03x00x00x00'
Пояснення: 'hhl' означає два коротких цілих числа (h 2 байти кожне), за якими йде довге (l зазвичай 4 або 8 байтів залежно від платформи). 'iii' пакує три 4-байтові цілі числа. Вихідні дані представлені в байтах (b''), що представляють двійкове кодування значень.
2.struct.unpack(): Він перетворює упаковані двійкові дані назад у значення Python. Він приймає рядок формату (fmt) і упакований двійковий рядок і повертає кортеж неупакованих значень. Синтаксис:
struct.unpack(рядок fmt)
- fmt: Рядок формату, який визначає спосіб розпакування даних.
- рядок: Упаковані двійкові дані, які потрібно розпакувати.
import struct var = struct . pack ( '?hil' True 2 5 445 ) print ( var ) tup = struct . unpack ( '?hil' var ) print ( tup ) var = struct . pack ( 'qf' 5 2.3 ) print ( var ) tup = struct . unpack ( 'qf' var ) print ( tup )
Вихід
b'x01x00x02x00x05x00x00x00xbdx01x00x00x00x00x00x00' (True 2 5 445) b'x05x00x00x00x00x00x00x0033x13@' (5 2.299999952316284)
Пояснення: Цей приклад спочатку пакує логічний (?), короткий (h), ціле число (i) і довгий (l) у байти. Потім struct.unpack() використовується для перетворення його назад у значення Python. Друга частина пакує довге довге ціле число (q) і float (f), а потім розпаковує їх назад. Зверніть увагу, як 2.3 стає 2.299999952... через точність float.
3. struct.calcsize(): Він повертає розмір (у байтах) структури, що відповідає рядку формату. Це корисно для визначення того, скільки місця потрібно для зберігання упакованих даних. Синтаксис:
struct.calcsize(fmt)
- fmt: рядок формату, який визначає макет даних.
import struct print ( struct . calcsize ( '?hil' )) print ( struct . calcsize ( 'qf' ))
Вихід
16 12
Пояснення: '?hil' вимагає 16 байт і 'qf' потребує 12 байт залежно від вирівнювання та платформи.
4. struct.pack_into() і struct.unpack_from(): Ці методи дозволяють безпосередньо пакувати та розпаковувати дані в/з буфера, починаючи з заданого зсуву. Це особливо корисно при роботі з попередньо виділеними буферами пам’яті або при роботі з двійковими даними, що зберігаються в пам’яті.
Синтаксис для struct.pack_into():
struct.pack_into(fmt buffer offset v1 v2 ...)
- fmt: рядок формату, що вказує макет даних.
- buffer: Буфер для запису (наприклад, ctypes.create_string_buffer).
- зсув: початкова позиція в буфері, де починається пакування.
- v1 v2 ...: значення, які потрібно запакувати в буфер.
Синтаксис для struct.unpack_from():
struct.unpack_from(fmt buffer offset=0)
- fmt: Рядок формату, що визначає макет даних.
- буфер: Буфер, що містить упаковані дані.
- зсув: Початкова позиція, з якої починається розпакування (необов’язково)
import struct import ctypes # Allocate buffer size = struct . calcsize ( 'hhl' ) buff = ctypes . create_string_buffer ( size ) # Pack into buffer struct . pack_into ( 'hhl' buff 0 2 2 3 ) # Unpack from buffer res = struct . unpack_from ( 'hhl' buff 0 ) print ( res )
Вихід
(2 2 3)
Пояснення: Тут буфер створюється за допомогою ctypes. struct.pack_into() вставляє значення в цей буфер із вказаним зміщенням (у цьому випадку 0). struct.unpack_from() потім зчитує дані з буфера.
Вплив порядку формату
Порядок символів формату може змінити упакований вивід через доповнення та вирівнювання. Це впливає як на байтовий вміст, так і на розмір результату.
Python import struct var = struct . pack ( 'bi' 56 0x12131415 ) print ( var ) print ( struct . calcsize ( 'bi' )) var = struct . pack ( 'ib' 0x12131415 56 ) print ( var ) print ( struct . calcsize ( 'ib' ))
Вихід
b'8x00x00x00x15x14x13x12' 8 b'x15x14x13x128' 5
Пояснення: 'bi' (байт int) може включати доповнення після байта, тоді як 'ib' (цілий байт) не потребує цього. Різниця розмірів (8 проти 5) показує, як вирівнювання впливає на розташування пам’яті.
Помилки обробки
Якщо з struct.pack() використовується неправильний тип даних, виникає struct.error. Використовуйте try-except для безпечної обробки таких випадків.
Python import struct try : struct . pack ( 'h' 'invalid' ) # Wrong type 'invalid' is a string but 'h' expects an integer except struct . error as e : print ( f 'Struct Error: { e } ' )
Вихід
Struct Error: required argument is not an integer
Пояснення: Це показує обробку помилок під час використання struct. 'h' очікує коротке ціле число, але надається рядок ('invalid'), що викликає struct.error. Блок try-except фіксує помилку та друкує змістовне повідомлення.
довідка https://docs.python.org/2/library/struct.html
Створіть вікторину