Python struct 學習筆記

吳奇峰
5 min readMay 3, 2021

--

最近在處理檔案資料需要使用到很多二進為轉換文字的使用,

自己也花一點時間做了一些學習,但看了很多次也找到一些資料,但一周後要開始用,又忘記了(年紀有了)。就想透過網路做一個簡單的學習筆記,也整理一下自己所學的內容。讓自己以後可以有個快速可以回顧。畢竟年紀有了,沒有那麼多記憶空間可以用

Python 下可以有一模組可以讓使用者快速做資料的重新整理,還有格式轉換。通常在一些簡單的單晶片的應用使用的都是二進位資料與文字(ASCII/UTF-8)或者16進位的顯示與轉換。剛好今天我需要用到,而且在python 就已經有這個好用的模組可以使用,完全不需要自己來,節省了很多寫應用程式的時間,非常適合大眾使用。

在 micropythun 下的 struct 模組名稱是 ustruct,u-代表 Micro 的意思。也表示兩者之間有一些差異,差異如下:

ustruct 只提供了以下幾個基本的功能

  • calcsize /pack /pack_into / unpack / unpack_from

而struct 提供了更多方便的方法,我覺得比較有用的是 iter_unpack( format , buffer ),因為它可以使用迭代的方式重複地做完轉換的事情。不過使用基本的unpack 也可以達到相同的效果,只是需要自己組合相關的流程。

因為所使用的是micropython,所以就寫一下這部分的筆記

pack() pack(fmt,v1,v2,…)

  • 將變數轉成對應的格式

unpack(fmt,string)

  • 將對應的格式轉回數據

calcsize(fmt)

  • 計算目前的格式用了多少記憶體

size/byte 的前缀: @, <, >, !.

byte在記憶體中的排列方式,通常使用在同一個作業系統下是不需要考慮這個問題,但在使用資料的傳輸時候就需要注意雙方的溝通基準。簡單說明如下表格與例子

  • @ :依據本機器的特性排列
  • < : ARM little endian
  • > : Big endian
  • ! : 網路資料排列
>>>struct.pack(‘@3b’,255,128,00)
b’\xff\x80\x00'
>>>struct.pack(‘@3i’,255,128,00)
b’\xff\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00'
>>>struct.pack(‘<3i’,255,128,00)
b’\x00\x00\x00\xff\x00\x00\x00\x80\x00\x00\x00\x00'
>>>struct.pack('!3i',255,128,00)
b'\x00\x00\x00\xff\x00\x00\x00\x80\x00\x00\x00\x00'

排>列的使用,需要注意的是在檔案,記憶體,網路傳遞上。

在python 你不確定時可以透過以下的方式來確認機器上面的排列

>>>import sys
>>> sys.byteorder
‘little’

格式: b, B, h, H, i, I, l, L, q, Q, s, P, f, d (最後2個需要浮點庫支持)

b : signed char     ,1 byte
B : unsigned char ,1 byte
h : short ,2 byte
H : unsigned short ,2 byte
i : int ,4 byte
I : unsigned int ,4 byte
l : long ,4 byte
L : unsigned long ,4 bytel
q : long long ,8 byte
Q : unsigned long long,8 byte
s : char []
P : char []
f : float , 4 byte 使用IEEE 754 binary32
d : double , 8byte 使用IEEE 754 binary64

任務開始

今天我的任務是需要將List 轉換成二進位存放到檔案,然後再讀出轉成List

作法與想法

使用List的作法要注意的是使用*a[]來取得一整個列表

這其中只使用到 'B'這一個格式的轉換

import struct as structa = [[255,0,0],[34,255,0],[4,3,0]]
b=[[]]*3
file = open (‘test.bin’,’wb’)
for i in range(3):
w_buffer = struct.pack(‘3B’,*a[i]) #轉換格式到 bytearray
file.write(w_buffer)
file.close()
file = open (‘test.bin’,’rb’)
for i in range(3):
r_buffer = file.read(3)
b[i] = struct.unpack(‘3B’,r_buffer)
print (b)
file.close()

執行的結果

[(255, 0, 0), (34, 255, 0), (4, 3, 0)]

你也許會發現轉換出來的資料變成tuple,但不影響到應用。

檔案內容如下截圖

test.bin

--

--

吳奇峰

來自新竹科學園區-喜歡拆解電子產品-學習與閱讀