Автор оригинала: Doug Hellmann.
Цель:
Преобразование между строками и двоичными данными.
Модуль struct
включает функции для преобразования между строками байтов и собственными типами данных Python, такими как числа и строки.
Функции против класса Struct
Для работы со структурированными значениями доступен набор функций уровня модуля, а также класс Struct
. Спецификаторы формата преобразуются из строкового формата в скомпилированное представление аналогично тому, как обрабатываются регулярные выражения. Преобразование требует некоторых ресурсов, поэтому обычно более эффективно выполнить его один раз при создании экземпляра Struct
и вызвать методы в экземпляре вместо использования функций уровня модуля. Во всех следующих примерах используется класс Struct
.
Упаковка и распаковка
Структуры поддерживают упаковку данных в строки и распаковку данных из строк с использованием спецификаторов формата, состоящих из символов, представляющих тип данных, и необязательных индикаторов количества и порядка байтов. Обратитесь к документации стандартной библиотеки за полным списком поддерживаемых спецификаторов формата.
В этом примере спецификатор вызывает целое или длинное целочисленное значение, двухбайтовую строку и число с плавающей запятой. Пробелы в спецификаторе формата включены для разделения индикаторов типа и игнорируются при компиляции формата.
struct_pack.py
import struct import binascii values (1, 'ab'.encode('utf-8'), 2.7) s struct.Struct('I 2s f') packed_data s.pack(*values) print('Original values:', values) print('Format string :', s.format) print('Uses :', s.size, 'bytes') print('Packed Value :', binascii.hexlify(packed_data))
В примере упакованное значение преобразуется в последовательность шестнадцатеричных байтов для печати с помощью binascii.hexlify ()
, поскольку некоторые символы являются нулевыми.
$ python3 struct_pack.py Original values: (1, b'ab', 2.7) Format string : I 2s f Uses : 12 bytes Packed Value : b'0100000061620000cdcc2c40'
Используйте unpack ()
для извлечения данных из упакованного представления.
struct_unpack.py
import struct import binascii packed_data binascii.unhexlify(b'0100000061620000cdcc2c40') s struct.Struct('I 2s f') unpacked_data s.unpack(packed_data) print('Unpacked Values:', unpacked_data)
Передача упакованного значения в unpack ()
возвращает в основном те же значения (обратите внимание на расхождение в значениях с плавающей запятой).
$ python3 struct_unpack.py Unpacked Values: (1, b'ab', 2.700000047683716)
Порядок байтов
По умолчанию значения кодируются с использованием понятия endianness из собственной библиотеки C. Этот выбор легко изменить, указав явную директиву порядка байтов в строке формата.
struct_endianness.py
import struct import binascii values (1, 'ab'.encode('utf-8'), 2.7) print('Original values:', values) endianness [ ('@', 'native, native'), (, 'native, standard'), ('<', 'little-endian'), ('>', 'big-endian'), ('!', 'network'), ] for code, name in endianness: s struct.Struct(code + ' I 2s f') packed_data s.pack(*values) print() print('Format string :', s.format, 'for', name) print('Uses :', s.size, 'bytes') print('Packed Value :', binascii.hexlify(packed_data)) print('Unpacked Value :', s.unpack(packed_data))
в таблице ниже перечислены спецификаторы порядка байтов, используемые Struct
.
Спецификаторы порядка байтов для структуры
Код
Смысл
Родной порядок
Родной стандарт
прямой порядок байтов
прямой порядок байтов
Сетевой заказ
$ python3 struct_endianness.py Original values: (1, b'ab', 2.7) Format string : @ I 2s f for native, native Uses : 12 bytes Packed Value : b'0100000061620000cdcc2c40' Unpacked Value : (1, b'ab', 2.700000047683716) Format string : = I 2s f for native, standard Uses : 10 bytes Packed Value : b'010000006162cdcc2c40' Unpacked Value : (1, b'ab', 2.700000047683716) Format string : < I 2s f for little-endian Uses : 10 bytes Packed Value : b'010000006162cdcc2c40' Unpacked Value : (1, b'ab', 2.700000047683716) Format string : > I 2s f for big-endian Uses : 10 bytes Packed Value : b'000000016162402ccccd' Unpacked Value : (1, b'ab', 2.700000047683716) Format string : ! I 2s f for network Uses : 10 bytes Packed Value : b'000000016162402ccccd' Unpacked Value : (1, b'ab', 2.700000047683716)
Буферы
Работа с двоичными упакованными данными обычно зарезервирована для ситуаций, чувствительных к производительности, или для передачи данных в модули расширения и из них. Эти случаи можно оптимизировать, избегая накладных расходов на выделение нового буфера для каждой упакованной структуры. Методы pack_into ()
и unpack_from ()
поддерживают запись непосредственно в предварительно выделенные буферы.
struct_buffers.py
import array import binascii import ctypes import struct s struct.Struct('I 2s f') values (1, 'ab'.encode('utf-8'), 2.7) print('Original:', values) print() print('ctypes string buffer') b ctypes.create_string_buffer(s.size) print('Before :', binascii.hexlify(b.raw)) s.pack_into(b, 0, *values) print('After :', binascii.hexlify(b.raw)) print('Unpacked:', s.unpack_from(b, 0)) print() print('array') a array.array('b', b'\0' * s.size) print('Before :', binascii.hexlify(a)) s.pack_into(a, 0, *values) print('After :', binascii.hexlify(a)) print('Unpacked:', s.unpack_from(a, 0))
Атрибут size
в Struct
сообщает нам, насколько большим должен быть буфер.
$ python3 struct_buffers.py Original: (1, b'ab', 2.7) ctypes string buffer Before : b'000000000000000000000000' After : b'0100000061620000cdcc2c40' Unpacked: (1, b'ab', 2.700000047683716) array Before : b'000000000000000000000000' After : b'0100000061620000cdcc2c40' Unpacked: (1, b'ab', 2.700000047683716)
Смотрите также
- стандартная библиотечная документация для структуры
- Заметки о переносе Python 2 на 3 для struct
- array – модуль
array
для работы с последовательностями значений фиксированного типа. binascii
– модульbinascii
для создания ASCII-представлений двоичных данных.- WikiPedia: Endianness – Объяснение порядка байтов и порядка байтов в кодировке.