1. 賦值語句的特點 賦值語句創建對象的引用:賦值語句總是創建對象的引用,而不是複製對象。因此,Python中的變數更像是指針,而不是數據儲存區域。 變數在首次賦值時會被創建:因此不需要提前聲明變數。 變數在引用前必須先賦值:如果引用未賦值的變數會報錯 2. 賦值語句的形式 (1. 普通形式 >>> ...
方法一:
使用struct模塊,特點輕量化,簡單易用。缺點就是可讀性不是太好,使用小數據臨時使用一下,對於大量的數據解析,寫起來比較繁瑣,顯得有點力不從心。
import struct
data = 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=0x11223344
packData: 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類型 | 位元組數 |
---|---|---|
c | c_char | 1 |
b | c_byte | 1 |
B | c_ubyte | 1 |
h | c_short | 2 |
H | c_ushort | 2 |
i | c_int | 4 |
I | c_uint | 4 |
q | c_longlong | 8 |
Q | c_ulonglong | 8 |
f | c_float | 4 |
d | c_double | 8 |
p | c_char_p | 4(64位系統為8) |
P | c_void_p | 4(64位系統為8) |
x | c_ubyte(占位padding位元組) | 1 |
方法二:
使用ctypes模塊高效的解析組裝二進位數據,這種方法和C比較類似,也更為強大。
import ctypes
class 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學習交流群:711312441
if __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:1
b2:0
b3:0
b4:1
lev:2
BB:aa
BC:bb
BD:cc
SS:eeff
其中out.bin文件中保存的數據,以十六進位查看如下:
92 aa bb cc ee ff