●Header
這輩子,沒這麼討厭a b c e d f過。
-Lambert Chen
在程式的世界裡,不同程式語言就像不同的國家,有屬於自己的語言及文法。就像Python的int,沒有定義int的範圍,要多大就多大,要正就正,要負就負。但到了C可就不同了,Unsigned int , Long , Unsigned float,每一種都有自己的邊界值。那在python中如何讓電腦看得懂不同語言,但相同的byte呢?就要依靠Struct了。
●儲存計算方式的差異
在電腦的儲存空間中,一個數值常常會被切分成4個bytes(也就是32bit),並儲存於連續的儲存空間中。每一個byte皆用16進制表示0~255(00~FF),而這些數字也像我們在用的10進制數字,會有個十百千萬,擺放的方式也些不同,有時是「萬千百十個」,有時是「個十百千萬」,這也就是電腦儲存器裡面的位元組序(Endianness)。
若電腦依照「左高右低」排序則為大端序(big-endian),反之則為小端序(little-endian)。
舉個例子 有一組數組 0x0A0B0C0D,依照端序不同有不同的儲存方式,解析時須特別注意。
| Address | big-endian | little-endian |
| 5000 | 0x0A | 0x0D |
| 5001 | 0x0B | 0x0C |
| 5002 | 0x0C | 0x0B |
| 5003 | 0x0D | 0x0A |
| Character | Byte Order | Size | Alignment |
| @ | native | native | native |
| = | native | standard | none |
| < | little-endian | standard | none |
| > | big-endian | standard | none |
| ! | network (= big-endian) | standard | none |
在Python 中使用 Struct模組時,也需特別留意端序的性質,一但端序搞混了,數值可是天壤之別呀!
馬上來看看Python如何將這些Hex透過Struct做解析吧
●Python Struct
Struct Module
Python提供了三種最常使用的方式來做Pack,Unpack。
import Struct
struct.pack(format,v1,v2) #將python元件打包成binary package
struct.unpack(format,buffer) #將binary package轉成python元件
struct.calcsize(*format) #依照format來計算需多少byte e.g. struct.calcsize('2I3s')
F

Pack,Unpack操作
這邊用簡單的Float,Hex互換來說明一下Pack及Unpack。
設定兩個數值 (Float:25.5 Hex:0x41cc0000),端序為小端序。
透過struct.pack()將數值打包成binary package,接著再使用struct.unpack()將binary package轉換回python 字串。
import struct
def float_to_hex(Float_num):
Float_num = float(Float_num)
return hex(struct.unpack('<I',struct.pack('<f',Float_num))[0]) #'<' little endian, 'f' 4 bytes float
def hex_to_float(Hex_num):
return float(struct.unpack('<f',struct.pack('<I',Hex_num))[0]) #'<' little endian, 'I' 4 bytes unsigned int
print(float_to_hex(25.5))
print(hex_to_float(0x41cc0000))
●Footer
以上就是Python對於binary package的常用處理方法,對於IoT專業人員,看到這些data就是要準備和他作戰,binary的東西只要任何一點疏忽,所換來的結果可是不容小覷的,處理binary講求謹慎,Struct Module提供了更多處理binary package的function,小弟拋磚引玉,歡迎大家討論分享~
參考資料
https://docs.python.org/3/library/struct.html
https://sanyuesha.com/2018/03/10/why-pack-unpack/
https://zh.wikipedia.org/wiki/%E5%AD%97%E8%8A%82%E5%BA%8F