struct
--- 將字節(jié)串解讀為打包的二進制數(shù)據(jù)?
源代碼: Lib/struct.py
此模塊可以執(zhí)行 Python 值和以 Python bytes
對象表示的 C 結(jié)構(gòu)之間的轉(zhuǎn)換。 這可以被用來處理存儲在文件中或是從網(wǎng)絡(luò)連接等其他來源獲取的二進制數(shù)據(jù)。 它使用 格式字符串 作為 C 結(jié)構(gòu)布局的精簡描述以及與 Python 值的雙向轉(zhuǎn)換。
備注
默認情況下,打包給定 C 結(jié)構(gòu)的結(jié)果會包含填充字節(jié)以使得所涉及的 C 類型保持正確的對齊;類似地,對齊在解包時也會被納入考慮。 選擇此種行為的目的是使得被打包結(jié)構(gòu)的字節(jié)能與相應(yīng) C 結(jié)構(gòu)在內(nèi)存中的布局完全一致。 要處理平臺獨立的數(shù)據(jù)格式或省略隱式的填充字節(jié),請使用 standard
大小和對齊而不是 native
大小和對齊:詳情參見 字節(jié)順序,大小和對齊方式。
某些 struct
的函數(shù)(以及 Struct
的方法)接受一個 buffer 參數(shù)。 這將指向?qū)崿F(xiàn)了 緩沖協(xié)議 并提供只讀或是可讀寫緩沖的對象。 用于此目的的最常見類型為 bytes
和 bytearray
,但許多其他可被視為字節(jié)數(shù)組的類型也實現(xiàn)了緩沖協(xié)議,因此它們無需額外從 bytes
對象復制即可被讀取或填充。
函數(shù)和異常?
此模塊定義了下列異常和函數(shù):
- exception struct.error?
會在多種場合下被引發(fā)的異常;其參數(shù)為一個描述錯誤信息的字符串。
- struct.pack(format, v1, v2, ...)?
返回一個 bytes 對象,其中包含根據(jù)格式字符串 format 打包的值 v1, v2, ... 參數(shù)個數(shù)必須與格式字符串所要求的值完全匹配。
- struct.pack_into(format, buffer, offset, v1, v2, ...)?
根據(jù)格式字符串 format 打包 v1, v2, ... 等值并將打包的字節(jié)串寫入可寫緩沖區(qū) buffer 從 offset 開始的位置。 請注意 offset 是必需的參數(shù)。
- struct.unpack(format, buffer)?
根據(jù)格式字符串 format 從緩沖區(qū) buffer 解包(假定是由
pack(format, ...)
打包)。 結(jié)果為一個元組,即使其只包含一個條目。 緩沖區(qū)的字節(jié)大小必須匹配格式所要求的大小,如calcsize()
所示。
- struct.unpack_from(format, /, buffer, offset=0)?
對 buffer 從位置 offset 開始根據(jù)格式字符串 format 進行解包。 結(jié)果為一個元組,即使其中只包含一個條目。 緩沖區(qū)的字節(jié)大小從位置 offset 開始必須至少為
calcsize()
顯示的格式所要求的大小。
- struct.iter_unpack(format, buffer)?
根據(jù)格式字符串 format 以迭代方式從緩沖區(qū) buffer 解包。 此函數(shù)返回一個迭代器,它將從緩沖區(qū)讀取相同大小的塊直至其內(nèi)容全部耗盡。 緩沖區(qū)的字節(jié)大小必須整數(shù)倍于格式所要求的大小,如
calcsize()
所示。每次迭代將產(chǎn)生一個如格式字符串所指定的元組。
3.4 新版功能.
- struct.calcsize(format)?
返回與格式字符串 format 相對應(yīng)的結(jié)構(gòu)的大小(亦即
pack(format, ...)
所產(chǎn)生的字節(jié)串對象的大?。?。
格式字符串?
格式字符串是用來在打包和解包數(shù)據(jù)時指定預(yù)期布局的機制。 它們使用指定被打包/解包數(shù)據(jù)類型的 格式字符 進行構(gòu)建。 此外,還有一些特殊字符用來控制 字節(jié)順序,大小和對齊方式。
字節(jié)順序,大小和對齊方式?
默認情況下,C類型以機器的本機格式和字節(jié)順序表示,并在必要時通過跳過填充字節(jié)進行正確對齊(根據(jù)C編譯器使用的規(guī)則)。
或者,根據(jù)下表,格式字符串的第一個字符可用于指示打包數(shù)據(jù)的字節(jié)順序,大小和對齊方式:
字符 |
字節(jié)順序 |
大小 |
對齊方式 |
---|---|---|---|
|
按原字節(jié) |
按原字節(jié) |
按原字節(jié) |
|
按原字節(jié) |
標準 |
無 |
|
小端 |
標準 |
無 |
|
大端 |
標準 |
無 |
|
網(wǎng)絡(luò)(=大端) |
標準 |
無 |
如果第一個字符不是其中之一,則假定為 '@'
。
本機字節(jié)順序可能為大端或是小端,取決于主機系統(tǒng)的不同。 例如, Intel x86 和 AMD64 (x86-64) 是小端的;Motorola 68000 和 PowerPC G5 是大端的;ARM 和 Intel Itanium 具有可切換的字節(jié)順序(雙端)。 請使用 sys.byteorder
來檢查你的系統(tǒng)字節(jié)順序。
本機大小和對齊方式是使用 C 編譯器的 sizeof
表達式來確定的。 這總是會與本機字節(jié)順序相綁定。
標準大小僅取決于格式字符;請參閱 格式字符 部分中的表格。
請注意 '@'
和 '='
之間的區(qū)別:兩個都使用本機字節(jié)順序,但后者的大小和對齊方式是標準化的。
形式 '!'
代表網(wǎng)絡(luò)字節(jié)順序總是使用在 IETF RFC 1700 中所定義的大端序。
沒有什么方式能指定非本機字節(jié)順序(強制字節(jié)對調(diào));請正確選擇使用 '<'
或 '>'
。
注釋:
填充只會在連續(xù)結(jié)構(gòu)成員之間自動添加。 填充不會添加到已編碼結(jié)構(gòu)的開頭和末尾。
當使用非本機大小和對齊方式即 '<', '>', '=', and '!' 時不會添加任何填充。
要將結(jié)構(gòu)的末尾對齊到符合特定類型的對齊要求,請以該類型代碼加重復計數(shù)的零作為格式結(jié)束。 參見 例子。
格式字符?
格式字符具有以下含義;C 和 Python 值之間的按其指定類型的轉(zhuǎn)換應(yīng)當是相當明顯的。 ‘標準大小’列是指當使用標準大小時以字節(jié)表示的已打包值大?。灰簿褪钱敻袷阶址?'<'
, '>'
, '!'
或 '='
之一開頭的情況。 當使用本機大小時,已打包值的大小取決于具體的平臺。
格式 |
C 類型 |
Python 類型 |
標準大小 |
備注 |
---|---|---|---|---|
|
填充字節(jié) |
無 |
||
|
char |
長度為 1 的字節(jié)串 |
1 |
|
|
signed char |
整數(shù) |
1 |
(1), (2) |
|
unsigned char |
整數(shù) |
1 |
(2) |
|
_Bool |
bool |
1 |
(1) |
|
short |
整數(shù) |
2 |
(2) |
|
unsigned short |
整數(shù) |
2 |
(2) |
|
int |
整數(shù) |
4 |
(2) |
|
unsigned int |
整數(shù) |
4 |
(2) |
|
long |
整數(shù) |
4 |
(2) |
|
unsigned long |
整數(shù) |
4 |
(2) |
|
long long |
整數(shù) |
8 |
(2) |
|
unsigned long long |
整數(shù) |
8 |
(2) |
|
|
整數(shù) |
(3) |
|
|
|
整數(shù) |
(3) |
|
|
(6) |
float |
2 |
(4) |
|
float |
float |
4 |
(4) |
|
double |
float |
8 |
(4) |
|
char[] |
字節(jié)串 |
||
|
char[] |
字節(jié)串 |
||
|
void* |
整數(shù) |
(5) |
在 3.3 版更改: 增加了對 'n'
和 'N'
格式的支持
在 3.6 版更改: 添加了對 'e'
格式的支持。
注釋:
'?'
轉(zhuǎn)換碼對應(yīng)于 C99 定義的 _Bool 類型。 如果此類型不可用,則使用 char 來模擬。 在標準模式下,它總是以一個字節(jié)表示。當嘗試使用任何整數(shù)轉(zhuǎn)換碼打包一個非整數(shù)時,如果該非整數(shù)具有
__index__()
方法,則會在打包之前調(diào)用該方法將參數(shù)轉(zhuǎn)換為一個整數(shù)。在 3.2 版更改: 增加了針對非整數(shù)使用
__index__()
方法的特性。'n'
和'N'
轉(zhuǎn)換碼僅對本機大小可用(選擇為默認或使用'@'
字節(jié)順序字符)。 對于標準大小,你可以使用適合你的應(yīng)用的任何其他整數(shù)格式。對于
'f'
,'d'
和'e'
轉(zhuǎn)換碼,打包表示形式將使用 IEEE 754 binary32, binary64 或 binary16 格式 (分別對應(yīng)于'f'
,'d'
或'e'
),無論平臺使用何種浮點格式。'P'
格式字符僅對本機字節(jié)順序可用(選擇為默認或使用'@'
字節(jié)順序字符)。 字節(jié)順序字符'='
選擇使用基于主機系統(tǒng)的小端或大端排序。 struct 模塊不會將其解讀為本機排序,因此'P'
格式將不可用。IEEE 754 binary16 "半精度" 類型是在 IEEE 754 標準 的 2008 修訂版中引入的。 它包含一個符號位,5 個指數(shù)位和 11 個精度位(明確存儲 10 位),可以完全精確地表示大致范圍在
6.1e-05
和6.5e+04
之間的數(shù)字。 此類型并不被 C 編譯器廣泛支持:在一臺典型的機器上,可以使用 unsigned short 進行存儲,但不會被用于數(shù)學運算。 請參閱維基百科頁面 half-precision floating-point format 了解詳情。
格式字符之前可以帶有整數(shù)重復計數(shù)。 例如,格式字符串 '4h'
的含義與 'hhhh'
完全相同。
格式之間的空白字符會被忽略;但是計數(shù)及其格式字符中不可有空白字符。
對于 's'
格式字符,計數(shù)會被解析為字節(jié)的長度,而不是像其他格式字符那樣的重復計數(shù);例如,'10s'
表示一個 10 字節(jié)的字節(jié)串,而 '10c'
表示 10 個字符。 如果未給出計數(shù),則默認值為 1。 對于打包操作,字節(jié)串會被適當?shù)亟財嗷蛱畛淇兆止?jié)以符合要求。 對于解包操作,結(jié)果字節(jié)對象總是恰好具有指定數(shù)量的字節(jié)。 作為特殊情況,'0s'
表示一個空字符串(而 '0c'
表示 0 個字符)。
當使用某一種整數(shù)格式 ('b'
, 'B'
, 'h'
, 'H'
, 'i'
, 'I'
, 'l'
, 'L'
, 'q'
, 'Q'
) 打包值 x
時,如果 x
在該格式的有效范圍之外則將引發(fā) struct.error
。
在 3.1 版更改: 在之前版本中,某些整數(shù)格式包裝了超范圍的值并會引發(fā) DeprecationWarning
而不是 struct.error
。
'p'
格式字符用于編碼“Pascal 字符串”,即存儲在由計數(shù)指定的 固定長度字節(jié) 中的可變長度短字符串。 所存儲的第一個字節(jié)為字符串長度或 255 中的較小值。 之后是字符串對應(yīng)的字節(jié)。 如果傳入 pack()
的字符串過長(超過計數(shù)值減 1),則只有字符串前 count-1
個字節(jié)會被存儲。 如果字符串短于 count-1
,則會填充空字節(jié)以使得恰好使用了 count 個字節(jié)。 請注意對于 unpack()
,'p'
格式字符會消耗 count
個字節(jié),但返回的字符串永遠不會包含超過 255 個字節(jié)。
對于 '?'
格式字符,返回值為 True
或 False
。 在打包時將會使用參數(shù)對象的邏輯值。 以本機或標準 bool 類型表示的 0 或 1 將被打包,任何非零值在解包時將為 True
。
例子?
備注
所有示例都假定使用一臺大端機器的本機字節(jié)順序、大小和對齊方式。
打包/解包三個整數(shù)的基礎(chǔ)示例:
>>> from struct import *
>>> pack('hhl', 1, 2, 3)
b'\x00\x01\x00\x02\x00\x00\x00\x03'
>>> unpack('hhl', b'\x00\x01\x00\x02\x00\x00\x00\x03')
(1, 2, 3)
>>> calcsize('hhl')
8
解包的字段可通過將它們賦值給變量或?qū)⒔Y(jié)果包裝為一個具名元組來命名:
>>> record = b'raymond \x32\x12\x08\x01\x08'
>>> name, serialnum, school, gradelevel = unpack('<10sHHb', record)
>>> from collections import namedtuple
>>> Student = namedtuple('Student', 'name serialnum school gradelevel')
>>> Student._make(unpack('<10sHHb', record))
Student(name=b'raymond ', serialnum=4658, school=264, gradelevel=8)
格式字符的順序可能對大小產(chǎn)生影響,因為滿足對齊要求所需的填充是不同的:
>>> pack('ci', b'*', 0x12131415)
b'*\x00\x00\x00\x12\x13\x14\x15'
>>> pack('ic', 0x12131415, b'*')
b'\x12\x13\x14\x15*'
>>> calcsize('ci')
8
>>> calcsize('ic')
5
以下格式 'llh0l'
指定在末尾有兩個填充字節(jié),假定 long 類型按 4 個字節(jié)的邊界對齊:
>>> pack('llh0l', 1, 2, 3)
b'\x00\x00\x00\x01\x00\x00\x00\x02\x00\x03\x00\x00'
這僅當本機大小和對齊方式生效時才會起作用;標準大小和對齊方式并不會強制進行任何對齊。
類?
struct
模塊還定義了以下類型:
- class struct.Struct(format)?
返回一個新的 Struct 對象,它會根據(jù)格式字符串 format 來寫入和讀取二進制數(shù)據(jù)。 一次性地創(chuàng)建 Struct 對象并調(diào)用其方法相比使用同樣的格式調(diào)用
struct
函數(shù)更為高效,因為這樣格式字符串只需被編譯一次。已編譯的 Struct 對象支持以下方法和屬性:
- pack_into(buffer, offset, v1, v2, ...)?
等價于
pack_into()
函數(shù),使用了已編譯的格式。
- unpack_from(buffer, offset=0)?
等價于
unpack_from()
函數(shù),使用了已編譯的格式。 緩沖區(qū)的字節(jié)大小從位置 offset 開始必須至少為size
。
- iter_unpack(buffer)?
等價于
iter_unpack()
函數(shù),使用了已編譯的格式。 緩沖區(qū)的大小必須為size
的整數(shù)倍。3.4 新版功能.
- format?
用于構(gòu)造此 Struct 對象的格式字符串。