Python之struct模块的使用
struct模块的作用
可以完成字节与原生Python数据类型(如数字和字符串)之间的转换
struct提供了一组处理结构值的模块级函数,另外还有一个Struct类。格式指示符将由字符串格式转换为一种编译表示,这与处理正则表达式的方式类似。
这个转换会耗费一些资源,所以创建一个Struct实例并在这个实例上调用方法时(不是使用模块级函数)只完成一次转换,这会更高效。
1、用struct.pack封包
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)) # 将数据转为十六进制显示
运行效果
Original values: (1, b'ab', 2.7) Format string : I 2s f Uses : 12 bytes Packed Value : b'0100000061620000cdcc2c40'
2、用struct.pack解包
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)
运行效果
Unpacked Values: (1, b'ab', 2.700000047683716)
3、以上封包与解包字节十六进制字节序列的总结
binascii.hexlify() #转变十六进制的字节序列 binascii.unhexlify()#将十六进制字节序列,转为字节
4、字节序的排序
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('=====>', code, name) 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))
运行效果
Original values: (1, b'ab', 2.7) =====> @ native, native Format string : @ I 2s f for native, native Uses : 12 bytes Packed Value : b'0100000061620000cdcc2c40' Unpacked Value : (1, b'ab', 2.700000047683716) =====> = native, standard Format string : = I 2s f for native, standard Uses : 10 bytes Packed Value : b'010000006162cdcc2c40' Unpacked Value : (1, b'ab', 2.700000047683716) =====> < little-endian Format string : < I 2s f for little-endian Uses : 10 bytes Packed Value : b'010000006162cdcc2c40' Unpacked Value : (1, b'ab', 2.700000047683716) =====> > big-endian Format string : > I 2s f for big-endian Uses : 10 bytes Packed Value : b'000000016162402ccccd' Unpacked Value : (1, b'ab', 2.700000047683716) =====> ! network Format string : ! I 2s f for network Uses : 10 bytes Packed Value : b'000000016162402ccccd' Unpacked Value : (1, b'ab', 2.700000047683716)
Struct的字节序指示符
代码 | 含义 |
---|---|
@ |
原生顺序 |
= |
原生标准 |
< |
小端 |
> |
大端 |
! |
网络顺序 |
5、缓冲区的使用
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) # 创建ctype字符串缓冲区 print(b) 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))
运行效果
Original: (1, b'ab', 2.7) ctypes string buffer <ctypes.c_char_Array_12 object at 0x000001D61B42F448> 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)