[Python标准库]struct——二进制数据结构
作用:在字符串和二进制数据之间转换。
Python 版本:1.4 及以后版本
struct 模块包括一些在字节串与内置 Python 数据类型(如数字和字符串)之间完成转换的函数。
函数与 Struct 类
struct 提供了一组处理结构的模块级函数,另外还有一个 Struct 类。格式指示符由字符串格式转换为一种编译表示,这与处理正则表达式的方式类似。这个转换会耗费资源,所以当创建一个 Struct 实例并在这个实例上调用方法时(而不是使用模块级函数),完成一次转换会更为高效。下面的例子都会使用 Struct 类。
打包和解包
Struct 支持使用格式指示符将数据打包(packing)为字符串,以及从字符串解包(unpacking)数据,格式提示符由表示数据类型的字符以及可选的数量及字节序(endianness)指示符构成,要全面了解目前支持的格式指示符,请参考标准库文档。
在下面的例子中,指示符要求有一个整数或 long 值、一个包含两字符的串,以及一个浮点数。格式指示符中包含的空格用来分隔类型指示符,在编译格式时会被忽略。
作用:在字符串和二进制数据之间转换。
Python 版本:1.4 及以后版本
struct 模块包括一些在字节串与内置 Python 数据类型(如数字和字符串)之间完成转换的函数。
函数与 Struct 类
struct 提供了一组处理结构的模块级函数,另外还有一个 Struct 类。格式指示符由字符串格式转换为一种编译表示,这与处理正则表达式的方式类似。这个转换会耗费资源,所以当创建一个 Struct 实例并在这个实例上调用方法时(而不是使用模块级函数),完成一次转换会更为高效。下面的例子都会使用 Struct 类。
打包和解包
Struct 支持使用格式指示符将数据打包(packing)为字符串,以及从字符串解包(unpacking)数据,格式提示符由表示数据类型的字符以及可选的数量及字节序(endianness)指示符构成,要全面了解目前支持的格式指示符,请参考标准库文档。
在下面的例子中,指示符要求有一个整数或 long 值、一个包含两字符的串,以及一个浮点数。格式指示符中包含的空格用来分隔类型指示符,在编译格式时会被忽略。
import struct
import binascii
values = (1, 'ab', 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() 打印,因为有些字符是 null。
使用 unpack() 可以从打包表示中抽取数据。
import struct
import binascii
packed_data = binascii.unhexlify('0100000061620000cdcc2c40')
s = struct.Struct('I 2s f')
unpacked_data = s.unpack(packed_data)
print 'Unpacked Values:', unpacked_data
将打包值传入 unpack(),基本上会得到相同的值(注意浮点值中的差别)。
字节序
默认情况下,值会使用内置 C 库的字节序(endianness)来编码。只需在格式串中提供一个显式的字节序命令,就可以很容易地覆盖这个默认选择。
import struct
import binascii
values = (1, 'ab', 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 使用的字节序提示符。
提示符
|
含义
|
@
|
内置顺序
|
=
|
内置标准
|
<
|
小端
|
>
|
大端
|
!
|
网络顺序
|
缓冲区
通常在重视性能的情况下或者向扩展模块传入或传出数据时才会处理二进制打包数据。通过避免为每一个打包结构分配一个新缓冲区所带来的开销,可以优化这些情况。pack_into() 和 unpack_from() 方法支持直接写入预分配的缓冲区。
通常在重视性能的情况下或者向扩展模块传入或传出数据时才会处理二进制打包数据。通过避免为每一个打包结构分配一个新缓冲区所带来的开销,可以优化这些情况。pack_into() 和 unpack_from() 方法支持直接写入预分配的缓冲区。
import struct
import binascii
s = struct.Struct(' I 2s f')
values = (1, 'ab', 2.7)
print 'Original:', values
print
print 'ctypes string buffer'
import ctypes
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'
import array
a = array.array('c', '\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)
Struct 的 size 属性指出缓冲区需要有多大。