方法一:

使用struct模块,特点轻量化,简单易用。缺点就是可读性不是太好,使用小数据临时使用一下,对于大量的数据解析,写起来比较繁琐,显得有点力不从心。

import structdata = b'\x92\xaa\xbb\xcc\x11\x22\x33\x44'a,b,c,d,e = struct.unpack(">BBBBI", data)print("a=0x%x b=0x%x c=0x%x d=0x%x e=0x%x"%(a,b,c,d,e))packData = struct.pack(">BBBBI", a, b, c, d, e)print("packData: %s"%packData)

上面的程序会按照给定的格式一次解析数据,得到的输出结果如下:

注:建议采用python3运行,python2不区分bytes和string类型,通过struct.pack()得到的结果为字符串类型,会打印出乱码。

a=0x92 b=0xaa c=0xbb d=0xcc e=0x11223344packData: b'\x92\xaa\xbb\xcc\x11"3D'

可以看出,能够正确的解析和组装出需要的的数据。

struct常用函数原型如下:

struct的方法说明
pack(fmt, v1, v2…)按照fmt指定的格式化要求,格式化v1,v2等后续参数,返回bytes类型
unpack(fmt, BytesData)按照fmt指定的格式要求,解析出bytesData里面的数据内容,返回的是数据元组
pack_from(fmt, BytesData, offset)按照fmt指定的格式要求,解析后面的内容,从offset处开始解析,返回的是数据元组

这个里面的fmt表示格式化字符串,由两个部分组成,第一部分为指定大小端格式,第二部分是依次解析的格式。

大小端格式字符说明.
> 大端模式和阅读顺序一致,高字节在前(内存地址小),低字节在后(地址大)。
<小端模式和大端相反,高字节在后(内存地址大),低字节在前面(地址小)。
@或者=主机默认字节序和主机系统强相关,X86/X64默认为小段模式。其中@还会强制4字节对齐。

解析格式如下:

格式字符ctypes类型字节数
cc_char1
bc_byte1
Bc_ubyte1
hc_short2
Hc_ushort2
ic_int4
Ic_uint4
qc_longlong8
Qc_ulonglong8
fc_float4
dc_double8
pc_char_p4(64位系统为8)
Pc_void_p4(64位系统为8)
xc_ubyte(占位padding字节)1

方法二:

使用ctypes模块高效的解析组装二进制数据,这种方法和C比较类似,也更为强大。

import ctypesclass TestBig_Struct(ctypes.BigEndianStructure):    _fields_=[        ('b1', ctypes.c_ubyte,1),        ('b2', ctypes.c_ubyte,1),        ('b3', ctypes.c_ubyte,1),        ('b4', ctypes.c_ubyte,1),        ('lev',ctypes.c_ubyte,4),        ('BB', ctypes.c_ubyte),        ('BC', ctypes.c_ubyte),        ('BD', ctypes.c_ubyte),        ('SS', ctypes.c_ushort),    ]    class Test_Struct(ctypes.Structure):    _fields_=[        ('b1', ctypes.c_ubyte, 1),        ('b2', ctypes.c_ubyte, 1),        ('b3', ctypes.c_ubyte, 1),        ('b4', ctypes.c_ubyte, 1),        ('lev',ctypes.c_ubyte, 4),        ('BB', ctypes.c_ubyte),        ('BC', ctypes.c_ubyte),        ('BD', ctypes.c_ubyte),        ('SS', ctypes.c_ushort),    ]#学习中遇到问题没人解答?小编创建了一个Python学习交流群:711312441if __name__ == '__main__':    test = Test_Struct();    test.b1 = 1;    test.b2 = 0;    test.b3 = 0;    test.b4 = 1;    test.lev = 2;    test.BB = 0xAA;    test.BC = 0xBB;    test.BD = 0xCC;    test.SS = 0xEEFF;    print ("defEndian", ctypes.string_at(ctypes.addressof(test), ctypes.sizeof(test)))    test = TestBig_Struct();    test.b1 = 1;    test.b2 = 0;    test.b3 = 0;    test.b4 = 1;    test.lev = 2;    test.BB = 0xAA;    test.BC = 0xBB;    test.BD = 0xCC;    test.SS = 0xEEFF;    print ("BigEndian", ctypes.string_at(ctypes.addressof(test), ctypes.sizeof(test)))    ctypes.memmove(ctypes.addressof(test), b'\x92\xaa\xbb\xcc\xee\xff', ctypes.sizeof(test));    print ("b1:%x"%test.b1)    print ("b2:%x"%test.b2)    print ("b3:%x"%test.b3)    print ("b4:%x"%test.b4)    print ("lev:%x"%test.lev)    print ("BB:%x"%test.BB)    print ("BC:%x"%test.BC)    print ("BD:%x"%test.BD)    print ("SS:%x"%test.SS)    with open("out.bin", "wb") as f:        f.write(ctypes.string_at(ctypes.addressof(test), ctypes.sizeof(test)));

从上面的实例,可以看出来,这个就是采用类似与C结构体的方式,直接解析映射来解析和组装数据。十分的强大。这个实例程序的运行结果如下。

defEndian b')\xaa\xbb\xcc\xff\xee'BigEndian b'\x92\xaa\xbb\xcc\xee\xff'b1:1b2:0b3:0b4:1lev:2BB:aaBC:bbBD:ccSS:eeff

其中out.bin文件中保存的数据,以十六进制查看如下:

92 aa bb cc ee ff