Ниже представлены несколько общих примеров использования функции модуля struct
.
В этом примере строка формата вызывает длинное целое значение, двухбайтовую строку и число с плавающей запятой. В строку формата включены пробелы для разделения индикаторов типа, которые будут проигнорированы при компиляции.
import struct import binascii values = (1, 'ab'.encode('utf-8'), 2.7) s = struct.Struct('@ I 2s f') packed_data = s.pack(*values) print('Строка формата:', s.format) print('Использовано памяти:', s.size, 'bytes') print('Упакованное значение:', binascii.hexlify(packed_data)) # Строка формата: I 2s f # Использовано памяти: 12 bytes # Упакованное значение: b'0100000061620000cdcc2c40'
Теперь достанем данные из упакованного представления.
import struct import binascii packed_data = binascii.unhexlify(b'0100000061620000cdcc2c40') s = struct.Struct('@ I 2s f') unpacked_data = s.unpack(packed_data) print('Оригинальное значение:', unpacked_data) # Оригинальное значение: (1, b'ab', 2.700000047683716)
Распакованные данные можно присваивать переменным используя операцию "присвоение распаковкой" или оборачивая результат в именованный кортеж:
>>> import struct >>> record = b'raymond \x32\x12\x08\x01\x08' # присвоение распаковкой >>> name, serialnum, school, gradelevel = struct.unpack('< 10s H H b', record) >>> print(name, serialnum, school, gradelevel) # b'raymond ' 4658 264 8 >>> from collections import namedtuple >>> Student = namedtuple('Student', 'name serialnum school gradelevel') # оборачиваем результат в именованный кортеж >>> Student._make(struct.unpack('< 10s H H b', record)) # Student(name=b'raymond ', serialnum=4658, school=264, gradelevel=8)
Работа с двоичными упакованными данными обычно резервируется для чувствительных к производительности ситуаций или для передачи данных в модули расширения и из них. Эти случаи можно оптимизировать, избегая затрат на выделение нового буфера для каждой упакованной структуры. Методы struct.pack_into()
и struct.unpack_from()
поддерживают прямую запись в заранее выделенные буферы.
import array, ctypes, binascii, struct s = struct.Struct('@I 2s f') values = (1, 'ab'.encode('utf-8'), 2.7) print('Original:', values) b = ctypes.create_string_buffer(s.size) a = array.array('b', b'\0' * s.size) print('\nBefore :', binascii.hexlify(a)) s.pack_into(a, 0, *values) print('After :', binascii.hexlify(a)) print('Unpacked:', s.unpack_from(a, 0)) # Original: (1, b'ab', 2.7) # # Before : b'000000000000000000000000' # After : b'0100000061620000cdcc2c40' # Unpacked: (1, b'ab', 2.700000047683716)
Атрибут size
объекта Struct
сообщает нам, насколько большим должен быть буфер.