Python struct pack format

POST

Python uses struct.pack() to pack python data type into binary data (Byte Stream), which means convert a value to a string based on the format.

Because there is no byte type in Python, where the string is equivalent to a byte stream, or byte array.

struct.pack()

struck.pack(format, data1, data2. )

format: define the converted format. data1,data2,…: the data needs to be packed.

Format C Type Python Type Standard Size
x pad byte
c char string of length 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
f float float 4
d double float 8
s char[] string
p char[]string
P void * integer

To exchange data with the structure in C, it is also necessary to consider that some C or C + + compilers use byte alignment, usually a 32-bit system with 4 bytes as the unit. Therefore, a struct can be converted according to the byte order of the local machine. The alignment can be changed by the first character in the format. The definition is as follows:

Format Byte Order Size alignment
@ native byte native native
= native standard none
little-endian char standard none
> big-endian char standard none
! network (= big-endian) standard none

Use it in the first place of format.

import struct a = 11 b = 12 print(len(struct.pack("ii",a,b))) 8 print(struct.pack("ii",a,b)) b'\x0b\x00\x00\x00\x0c\x00\x00\x00'

struct.unpack()

struct.unpack() unpacks the byte stream into Python data type.
The function prototype:

This function return a tuple.

a = 11 b = 12 packdata = struct.pack("ii",a,b) c,d = struct.unpack("1i1i",packdata) print((c,d)) (11,12)

struct.calcsize()

Struct.calcsize() is used to calculate the length of the result corresponding to the format string.

print(struct.calcsize("c")) 1 print(struct.calcsize("H")) 2 print(struct.calcsize("L")) 4 print(struct.calcsize("Q")) 8

This article introduced the Python struct.pack() method.

Источник

Пакуем байты на Python: struct

Кто сказал, что нельзя делать низкоуровневые вещи на Python? Конечно, можно. Давайте научимся упаковывать данные из Python в байты и распаковывать их обратно.

Встроенный модуль struct как раз создан для этих целей. В низкоуровневом деле важны детали, а именно размер каждого элемента данных, их порядок в структуре, а также порядок байт для многобайтовых типов данных. Для определения этих деталей модуль struct вводит форматные строки (не путать с str.format, там другой формат).

Начнем с простого примера:

>>> import struct >>> struct.pack("hhl", 1, 2, 3) b'\x01\x00\x02\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00'

Здесь происходит вот что. Мы берем три числа: 1, 2, 3 и пакуем их в байты, таким образом, что первое и второе числа трактуются как тип short int (4 байта на моей машине), а последнее, как long int (8 байт на моей машине). Это типы не из Python, а из языка Си. Ознакомьтесь с типами языка Си, если хотите понимать, что они из себя представляют и какой размер в байтах имеют.

Обратная распаковка байт в кортеж значений по заданному формату:

>>> struct.unpack("hhl", b'\x01\x00\x02\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00') (1, 2, 3)

Форматы запаковки и распаковки должны совпадать, иначе данные будут неправильно интерпретированы или испорчены, или же вообще возникнет ошибка из-за того, что размер данных не подходит под ожидаемый формат (struct.error):

>>> struct.unpack("hhl", b'\x01\x02\x03') Traceback (most recent call last): File "", line 1, in struct.error: unpack requires a buffer of 16 bytes

Обратите внимание, что я выше писал, что размер элемента «h» – 4 байта именно на моей машине. Может статься так, что на машине с другим процессором, архитектурой или просто с другой версией ОС размер типа будет другой. Для 32 битных систем, это обычно будет 2 байта.

Но, что если данных передаются по сети или через носители информации между системами с разной или неизвестной заранее архитектурой? Конечно, у struct есть средства на такие случаи. Первый символ форматной строки обозначит порядок байт. Обратите внимание на таблицу:

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

Нативный – значит родной для конкретно вашей машины и системы. По умолчанию порядок байт и размер типов данных как раз нативный (символ @).

Стандартный размер – размер, который фиксирован стандартом и не зависит от текущей платформы. Например, char всегда 1 байт, а int – 4 байта. Если мы планируем распространять запакованные байты, мы должны гарантировать, что размер типов будет всегда стандартный. Для этого подходит любой из символов «=«, ««, «>«, «!» в начале форматной строки.

Little-endian и big-endian

Little-endian и big-endian – это два основных порядка байт. Представим, что у нас есть короткое целое (short int), и оно занимает два (2) байта. Какой из байтов должен идти сначала, а какой в конце?

В big-endian порядок от старшего байта к младшему. В little-endian порядок от младшего байта к старшему. Как узнать на Python какой порядок байт в системе:

>>> import sys >>> sys.byteorder 'little'

Давайте наглядно посмотрим как пакуются байты при разных порядках. Для числа 258 в форме short младший байт будет = 2, а старший = 1:

>>> struct.pack(">> struct.pack(">h", 258) # big-endian b'\x01\x02'

Как видите порядок байт противоположный для разных случаев.

В сетевых протоколах принято использовать big-endian (символ «!» – псевдоним к «>«), а на большинстве современных настольных систем используется little-endian.

Таблица типов данных

Теперь ознакомимся с таблицей типов данных, которая дает соответствие символу форматной строки (код преобразования) с Си-типом данных, Python-типом данных и стандартный размером. Еще раз: стандартный размер будет только, если задан первый символ как ««, «>«, «!» или «=«. Для «@» или по умолчанию – размер данных определяется текущей системой (платформо-зависимо).

Символ Тип в языке Си Python тип Станд. размер
x байт набивки нет значения
c char bytes длины 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 указывается явно

Коды «e«, «f«, «d» используют бинарный формат IEEE-754.

Код «x» это просто байт набивки. Он не попадает в распакованные данные, а нужен, чтобы выравнивать данные. «x» при запаковке забиваются пустыми байтами. Пример: «пусто-число-пусто-пусто-число-пусто»:

>>> struct.pack(">xBxxBx", 255, 128) b'\x00\xff\x00\x00\x80\x00' >>> struct.unpack('>xBxxBx', b'\x00\xff\x00\x00\x80\x00') (255, 128)

О форматной строке

Если в форматной строке перед символом кода – число, то значит этот символ повторяется столько раз, сколько указывает число. Два кусочка кода аналогичны:

>>> struct.pack(">3h", 1, 2, 3) b'\x00\x01\x00\x02\x00\x03' >>> struct.pack(">hhh", 1, 2, 3) b'\x00\x01\x00\x02\x00\x03'

Для строк (коды «s» и «p«) надо указывать число байт – длину строки, иначе будет считаться 1 байт:

>>> struct.pack("ss", b"abc", b"XYZW") # не указал длину - потерял байты b'aX' >>> struct.pack("3s4s", b"abc", b"XYZW") b'abcXYZW'

10s – одна 10-символьная строка, а 10c – 10 отдельных символов:

>>> struct.unpack('10c', b'abracadabr') (b'a', b'b', b'r', b'a', b'c', b'a', b'd', b'a', b'b', b'r') >>> struct.unpack('10s', b'abracadabr') (b'abracadabr',)

Можно вставлять пробелы между отдельными элементами форматной строки (но нельзя отделать число от символа). Пробелы игнорируются при чтении строки и нужны для удобства чтения кода программистом:

>>> struct.pack('>6sh?', b'python', 65, True) b'python\x00A\x01' >>> struct.pack('> 6s h ?', b'python', 65, True) # тоже, но с пробелами b'python\x00A\x01' >>> struct.unpack('> 6s h ?', b'python\x00A\x01') (b'python', 65, True)

Полезности

Можно вычислить размер данных из форматной строки без фактической запаковки или распаковки данных:

Удобно распаковывать байты прямо в именованные кортежи:

>>> from collections import namedtuple >>> Student = namedtuple('Student', 'name serialnum school gradelevel') >>> record = b'raymond \x32\x12\x08\x01\x08' >>> Student._make(struct.unpack('

Запаковка в буффер со смещением struct.pack_into(format, buffer, offset, v1, v2, . ) :

>>> buffer = bytearray(40) >>> struct.pack_into('h l', buffer, 10, 3432, 340840) >>> buffer bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00h\r\x00\x00\x00\x00\x00\x00h3\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00') >>>

Распаковка из буффера со смещением:

>>> x, y = struct.unpack_from('h l', buffer, 10) >>> x, y (3432, 340840)

Распаковка нескольких однотипных структур:

>>> chunks = struct.pack('hh', 10, 20) * 5 >>> chunks # 5 одинаковых штук b'\n\x00\x14\x00\n\x00\x14\x00\n\x00\x14\x00\n\x00\x14\x00\n\x00\x14\x00' >>> [(x, y) for x, y in struct.iter_unpack('hh', chunks)] [(10, 20), (10, 20), (10, 20), (10, 20), (10, 20)]

Специально для канала @pyway. Подписывайтесь на мой канал в Телеграм @pyway 👈

Источник

Python struct pack, unpack

Python struct pack, unpack

While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.

Python struct module is capable of performing the conversions between the Python values and C structs, which are represented as Python Strings.

Python Struct

  • Python struct module can be used in handling binary data stored in files, database or from network connections etc.
  • It uses format Strings as compact descriptions of the layout of the C structs and the intended conversion to/from Python values.

Python Struct Functions

There are five important functions in struct module - pack() , unpack() , calcsize() , pack_into() and unpack_from() . In all these functions, we have to provide the format of the data to be converted into binary. Some of the popular format characters are:

?: boolean h: short l: long i: int f: float q: long long int 

You can get the complete list of format characters here. Let’s start looking into struct module functions one by one.

Python struct.pack()

This function packs a list of values into a String representation of the specified type. The arguments must match the values required by the format exactly. Let’s quickly look at struct pack() example:

import struct var = struct.pack('hhl', 5, 10, 15) print(var) var = struct.pack('iii', 10, 20, 30) print(var) 

python struct pack

When we run this script, we get the following representation: Note that ‘b’ in the Output stands for binary.

Python struct.unpack()

This function unpacks the packed value into its original representation with the specified format. This function always returns a tuple, even if there is only one element. Let’s quickly look at struct unpack() function example:

import struct var = struct.pack('hhl', 5, 10, 15) print(var) print(struct.unpack('hhl', var)) 

python struct unpack

When we run this script, we get back our original representation: Clearly, we must tell the Python interpreter the format we need to unpack the values into.

Python struct calcsize()

This function calculates and returns the size of the String representation of struct with a given format. Size is calculated in terms of bytes. Let’s quickly look at an example code snippet:

import struct var = struct.pack('hhl', 5, 10, 15) print(var) print("Size of String representation is <>.".format(struct.calcsize('hhl'))) 

python struct calcsize

When we run this script, we get the following representation:

Python struct pack_into(), unpack_from()

These functions allow us to pack the values into string buffer and unpack from a string buffer. These functions are introduced in version 2.5.

import struct # ctypes is imported to create a string buffer import ctypes # As shown in previous example size = struct.calcsize('hhl') print(size) # Buffer 'buff' is created from ctypes buff = ctypes.create_string_buffer(siz) # struct.pack_into() packs data into buff and it doesn't return any value # struct.unpack_from() unpacks data from buff, returns a tuple of values print(struct.pack_into('hhl', buff, 0, 5, 10, 15)) print(struct.unpack_from('hhl', buff, 0)) 

Python Struct pack_into and unpack_from string buffer

When we run this script, we get the following representation: That’s all for a short introduction of python struct module.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Источник

Читайте также:  Кластерный анализ python пример
Оцените статью