Python 沒有原生 bytes 型別(Python 2 以 str 兼任),處理二進位協議、檔案格式、網路封包時,struct 模組是連接 Python 物件與 C 風格二進位結構的關鍵橋樑。本文完整解析格式字元、位元組序、實戰解析 BMP 檔頭。
| 函式 | 用途 | 簽名 |
|---|---|---|
pack | Python 值 → bytes | pack(fmt, v1, v2, ...) |
unpack | bytes → Python 值元組 | unpack(fmt, buffer) |
calcsize | 格式字串佔用位元組數 | calcsize(fmt) |
| 字元 | C 型別 | Python 型別 | 大小 | 說明 |
|---|---|---|---|---|
x | pad byte | 無 | 1 | 填充位元組 |
c | char | bytes (長度1) | 1 | |
b | signed char | int | 1 | |
B | unsigned char | int | 1 | |
h | short | int | 2 | |
H | unsigned short | int | 2 | |
i | int | int | 4 | |
I | unsigned int | int | 4 | |
l | long | int | 4 | |
L | unsigned long | int | 4 | |
q | long long | int | 8 | |
Q | unsigned long long | int | 8 | |
f | float | float | 4 | 單精度 |
d | double | float | 8 | 雙精度 |
s | char[] | bytes | n | 固定長度字串 |
p | char[] | bytes | n | Pascal 字串(首位元組為長度) |
| 前綴 | 序 | 適用場景 |
|---|---|---|
@ | 原生 | 預設,視平台而定(不建議跨平台用) |
= | 原生標準 | 無對齊,標準大小 |
< | Little-endian | Intel x86、BMP、WAV、大多數檔案格式 |
> | Big-endian (Network) | 網路協議 (IP/TCP)、Java、Motorola 68k |
! | Network (= >) | 網路標準序,明確語意 |
import struct
# 32-bit 無號整數,Big-endian
packed = struct.pack('>I', 10240099)
print(packed) # b'\x00\x9c@c'
print(struct.unpack('>I', packed)) # (10240099,)
# 組合:Big-endian, uint32 + uint16
data = struct.pack('>IH', 4042322160, 32896)
print(struct.unpack('>IH', data)) # (4042322160, 32896)
# 浮點數
struct.pack('>f', 3.14159)
struct.pack('>d', 3.141592653589793)
BMP 採 Little-endian (<):
import struct
def parse_bmp_header(filepath):
with open(filepath, 'rb') as f:
header = f.read(30) # 讀前 30 位元組
if len(header) < 30:
raise ValueError('檔案太小,非有效 BMP')
# 格式:2字元 + 4整數*4 + 2短整數*2 = 30 bytes
#
# 預編譯格式,重複使用避免重新解析格式字串
bmp_header_struct = struct.Struct('
# 字串長度不固定:先讀長度,再讀內容
# 格式: bytes:
return struct.pack('
>>> struct.calcsize('ci') # char + int,可能有 3 bytes padding
8
>>>> struct.calcsize('=ci') # 標準大小,無對齊
5
跨平台序列化務必使用 = 或 </> 明確指定,避免 @ 原生模式導致不同架構不相容。
| 場景 | 推薦工具 |
|---|---|
| 簡單二進位協議、檔案頭解析 | struct |
| 複雜巢狀結構、陣列、指標 | ctypes / construct |
| 高效能數值陣列 | numpy / array 模組 |
| 通用序列化 | msgpack / protobuf / pickle |
struct 是 Python 處理二進位資料的基石,掌握格式字元、位元組序前綴、Struct 物件重用三大核心,即可輕鬆解析網路封包、二進位檔案格式、硬體裝置通訊協議。記住:跨平台必須顯式指定位元組序。