Python標準庫筆記(6) — struct模塊

来源:https://www.cnblogs.com/jhao/archive/2018/02/22/8458029.html
-Advertisement-
Play Games

該模塊作用是完成Python數值和C語言結構體的Python字元串形式間的轉換。這可以用於處理存儲在文件中或從網路連接中存儲的二進位數據,以及其他數據源。 用途: 在Python基本數據類型和二進位數據之間進行轉換 模塊提供了用於在位元組字元串和Python原生數據類型之間轉換函數,比如數字和字元串。 ...


該模塊作用是完成Python數值和C語言結構體的Python字元串形式間的轉換。這可以用於處理存儲在文件中或從網路連接中存儲的二進位數據,以及其他數據源。

用途: 在Python基本數據類型和二進位數據之間進行轉換

struct模塊提供了用於在位元組字元串和Python原生數據類型之間轉換函數,比如數字和字元串。

模塊函數和Struct類

它除了提供一個Struct類之外,還有許多模塊級的函數用於處理結構化的值。這裡有個格式符(Format specifiers)的概念,是指從字元串格式轉換為已編譯的表示形式,類似於正則表達式的處理方式。通常實例化Struct類,調用類方法來完成轉換,比直接調用模塊函數有效的多。下麵的例子都是使用Struct類。

Packing(打包)和Unpacking(解包)

Struct支持將數據packing(打包)成字元串,並能從字元串中逆向unpacking(解壓)出數據。

在本例中,格式指定器(specifier)需要一個整型或長整型,一個兩個位元組的string,和一個浮點數。格式符中的空格用於分隔各個指示器(indicators),在編譯格式時會被忽略。

import struct

import binascii

values = (1, 'ab'.encode('utf-8'), 2.7)
s = struct.Struct('I 2s f')
packed_data = s.pack(*values)

print('原始值:', values)
print('格式符:', s.format)
print('占用位元組:', s.size)
print('打包結果:', binascii.hexlify(packed_data))
# output
原始值: (1, b'ab', 2.7)
格式符: b'I 2s f'
占用位元組: 12
打包結果: b'0100000061620000cdcc2c40'

這個示例將打包的值轉換為十六進位位元組序列,用binascii.hexlify()方法列印出來。

使用unpack()方法解包。

import struct
import binascii

packed_data = binascii.unhexlify(b'0100000061620000cdcc2c40')

s = struct.Struct('I 2s f')
unpacked_data = s.unpack(packed_data)
print('解包結果:', unpacked_data)
# output
解包結果: (1, b'ab', 2.700000047683716)

將打包的值傳給unpack(),基本上返回相同的值(浮點數會有差異)。

位元組順序/大小/對齊

預設情況下,pack是使用本地C庫的位元組順序來編碼的。格式化字元串的第一個字元可以用來表示填充數據的位元組順序、大小和對齊方式,如下表所描述的:

Character Byte order Size Alignment
@ 本地 本地 本地
= 本地 standard none
< little-endian(小位元組序) standard none
> big-endian(大位元組序) standard none
! network (= big-endian) standard none

如果格式符中沒有設置這些,那麼預設將使用 @

本地位元組順序是指位元組順序是由當前主機系統決定。比如:Intel x86和AMD64(x86-64)使用小位元組序; Motorola 68000和 PowerPC G5使用大位元組序。ARM和Intel安騰支持切換位元組序。可以使用sys.byteorder查看當前系統的位元組順序。

本地大小(Size)和對齊(Alignment)是由c編譯器的sizeof表達式確定的。它與本地位元組順序對應。

標準大小由格式符確定,下麵會講各個格式的標準大小。

示例:

import struct
import binascii

values = (1, 'ab'.encode('utf-8'), 2.7)
print('原始值  : ', values)

endianness = [
    ('@', 'native, native'),
    ('=', 'native, standard'),
    ('<', 'little-endian'),
    ('>', 'big-endian'),
    ('!', 'network'),
]

for code, name in endianness:
    s = struct.Struct(code + ' I 2s f')
    packed_data = s.pack(*values)
    print()
    print('格式符  : ', s.format, 'for', name)
    print('占用位元組: ', s.size)
    print('打包結果: ', binascii.hexlify(packed_data))
    print('解包結果: ', s.unpack(packed_data))
# output
原始值  :  (1, b'ab', 2.7)

格式符  :  b'@ I 2s f' for native, native
占用位元組:  12
打包結果:  b'0100000061620000cdcc2c40'
解包結果:  (1, b'ab', 2.700000047683716)

格式符  :  b'= I 2s f' for native, standard
占用位元組:  10
打包結果:  b'010000006162cdcc2c40'
解包結果:  (1, b'ab', 2.700000047683716)

格式符  :  b'< I 2s f' for little-endian
占用位元組:  10
打包結果:  b'010000006162cdcc2c40'
解包結果:  (1, b'ab', 2.700000047683716)

格式符  :  b'> I 2s f' for big-endian
占用位元組:  10
打包結果:  b'000000016162402ccccd'
解包結果:  (1, b'ab', 2.700000047683716)

格式符  :  b'! I 2s f' for network
占用位元組:  10
打包結果:  b'000000016162402ccccd'
解包結果:  (1, b'ab', 2.700000047683716)

格式符

格式符對照表如下:

Format C Type Python type Standard size Notes
x pad byte no value
c char bytes of length 1 1
b signed char integer 1 (1),(3)
B unsigned char integer 1 (3)
? _Bool bool 1 (1)
h short integer 2 (3)
H unsigned short integer 2 (3)
i int integer 4 (3)
I unsigned int integer 4 (3)
l long integer 4 (3)
L unsigned long integer 4 (3)
q long long integer 8 (2), (3)
Q unsigned long long integer 8 (2), (3)
n ssize_t integer (4)
N size_t integer (4)
f float float 4 (5)
d double float 8 (5)
s char[] bytes
p char[] bytes
P void * integer (6)

緩衝區

將數據打包成二進位通常是用在對性能要求很高的場景。
在這類場景中可以通過避免為每個打包結構分配新緩衝區的開銷來優化。
pack_into()unpack_from()方法支持直接寫入預先分配的緩衝區。

import array
import binascii
import ctypes
import struct

s = struct.Struct('I 2s f')
values = (1, 'ab'.encode('utf-8'), 2.7)
print('原始值:', values)

print()
print('使用ctypes模塊string buffer')

b = ctypes.create_string_buffer(s.size)
print('原始buffer  :', binascii.hexlify(b.raw))
s.pack_into(b, 0, *values)
print('打包結果寫入 :', binascii.hexlify(b.raw))
print('解包        :', s.unpack_from(b, 0))

print()
print('使用array模塊')

a = array.array('b', b'\0' * s.size)
print('原始值   :', binascii.hexlify(a))
s.pack_into(a, 0, *values)
print('打包寫入 :', binascii.hexlify(a))
print('解包     :', s.unpack_from(a, 0))
# output
原始值: (1, b'ab', 2.7)

使用ctypes模塊string buffer
原始buffer  : b'000000000000000000000000'
打包結果寫入 : b'0100000061620000cdcc2c40'
解包        : (1, b'ab', 2.700000047683716)

使用array模塊
原始值   : b'000000000000000000000000'
打包寫入 : b'0100000061620000cdcc2c40'
解包     : (1, b'ab', 2.700000047683716)

博客原文: http://www.spiderpy.cn/blog/detail/37


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 其實在早之前,就做過 "立馬理財" 的銷售額統計,只不過是用前端js寫的,需要在首頁的console調試面板里粘貼一段代碼執行, "點擊這裡" 。主要是通過定時爬取 " " 非同步介面來獲取數據。然後通過一定的排重演算法來獲取最終的數據。但是這樣做有以下缺點: 0. 代碼只能在瀏覽器視窗下運行,關閉瀏覽 ...
  • 這個項目做得比較早,當時是基於ionic1和angular1做的。做了四個tabs的app,首頁模仿攜程首頁,第二頁主要是phonegap調用手機核心功能,第三頁模仿微信和qq聊天頁,第四頁模仿一般手機的表單設置頁。同時還模仿知乎做了一個側邊欄頁(賬號:wty,密碼:123456)。 沒有後臺,純前 ...
  • 這個項目最初其實是fork別人的項目。當初想接觸下mongodb資料庫,找個例子學習下,後來改著改著就面目全非了。後臺和資料庫重構,前端增加了登錄註冊功能,僅保留了博客設置頁面,但是也優化了。 "線上地址" 一、更新內容 0. 資料庫重新設計,改成以用戶分組的subDocs資料庫結構 0. 應資料庫 ...
  • 前言 進入自己github主頁會看到自己的提交記錄,如果某天沒有提交記錄,那天的小方框就顯示灰色。強迫症的我,每次進來看著就感覺不爽, 想著自己每天記得提交點東西,爭取像 "阮一峰" 大神一樣,每天都有提交記錄。 但是,畢竟是人,哪天忙了就會忘記提交,所以想著能不能實現在自己阿裡雲伺服器(linux ...
  • 關於元素居中的總結 包括:1.不使用定位 a.水平居中 b.垂直居中 c.其他居中 2.使用定位 a.父元素高寬固定 ... ...
  • 首先下載eCharts源代碼,然後可以按照官網的5分鐘上手ECharts教程做一個簡單的例子,這裡為了將前端顯示和後端邏輯分開,可以建一個index.html和一個繪製圖表的chartTest.js,代碼如下: js代碼如下: 通過上面的代碼就可以繪製出下麵這樣的一個簡單的圖表 其中xAxis和yA ...
  • 作為軟體開發人員,我們已知道思考如何將應用程式因數分解成組件部分。 這是對象導向、軟體抽象和組件化的中心模式。 現在,這種因數分解往往以共用庫和技術層之間的類與介面呈現。 通常採用一種分層方法,有後端存儲、中間層業務邏輯和前端用戶界面 (UI)。 過去幾年來的變化是身為開發人員的我們,開始為業務驅動 ...
  • 一致性演算法 是分散式系統中最重要的問題之一。錶面上看,這似乎很簡單,只是讓幾個節點在某些方面達成一致。在本篇之中,會帶大家完整的梳理分散式系統之中的共識演算法,來更加深刻的理解分散式系統的設計。 1.原子提交和兩階段提交(2PC) 原子提交防止了資料庫處於半更新的狀態,這對於需要滿足多對象事務和維護次 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...