Python基础教程— Struct模块
struct模塊提供了用于在字節(jié)字符串和Python原生數(shù)據(jù)類型之間轉(zhuǎn)換函數(shù),比如數(shù)字和字符串。
該模塊作用是完成Python數(shù)值和C語(yǔ)言結(jié)構(gòu)體的Python字符串形式間的轉(zhuǎn)換。
這可以用于處理存儲(chǔ)在文件中或從網(wǎng)絡(luò)連接中存儲(chǔ)的二進(jìn)制數(shù)據(jù),以及其他數(shù)據(jù)源。
1. 模塊函數(shù)和Struct類
它除了提供一個(gè)Struct類之外,還有許多模塊級(jí)的函數(shù)用于處理結(jié)構(gòu)化的值。這里有個(gè)格式符(Format specifiers)的概念,是指從字符串格式轉(zhuǎn)換為已編譯的表示形式,類似于正則表達(dá)式的處理方式。通常實(shí)例化Struct類,調(diào)用類方法來(lái)完成轉(zhuǎn)換,比直接調(diào)用模塊函數(shù)有效的多。下面的例子都是使用Struct類。
2. Packing(打包)和Unpacking(解包)
Struct支持將數(shù)據(jù)packing(打包)成字符串,并能從字符串中逆向unpacking(解壓)出數(shù)據(jù)。
在本例中,格式指定器(specifier)需要一個(gè)整型或長(zhǎng)整型,一個(gè)兩個(gè)字節(jié)的string,和一個(gè)浮點(diǎn)數(shù)。格式符中的空格用于分隔各個(gè)指示器(indicators),在編譯格式時(shí)會(huì)被忽略。
import structimport binasciivalues = (1, 'ab'.encode('utf-8'), 2.7) s = struct.Struct('I 2s f') packed_data = s.pack(*values)print('原始值:', values) print('格式符:', s.format) print('占用字節(jié):', s.size) print('打包結(jié)果:', binascii.hexlify(packed_data))# output 原始值: (1, b'ab', 2.7) 格式符: b'I 2s f' 占用字節(jié): 12 打包結(jié)果: b'0100000061620000cdcc2c40'這個(gè)示例將打包的值轉(zhuǎn)換為十六進(jìn)制字節(jié)序列,用binascii.hexlify()方法打印出來(lái)。
使用unpack()方法解包。
''' 遇到問題沒人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:531509025 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書! ''' import struct import binasciipacked_data = binascii.unhexlify(b'0100000061620000cdcc2c40')s = struct.Struct('I 2s f') unpacked_data = s.unpack(packed_data) print('解包結(jié)果:', unpacked_data)# output 解包結(jié)果: (1, b'ab', 2.700000047683716)將打包的值傳給unpack(),基本上返回相同的值(浮點(diǎn)數(shù)會(huì)有差異)。
3. 字節(jié)順序/大小/對(duì)齊
默認(rèn)情況下,pack是使用本地C庫(kù)的字節(jié)順序來(lái)編碼的。格式化字符串的第一個(gè)字符可以用來(lái)表示填充數(shù)據(jù)的字節(jié)順序、大小和對(duì)齊方式,如下表所描述的:
如果格式符中沒有設(shè)置這些,那么默認(rèn)將使用 @。
本地字節(jié)順序是指字節(jié)順序是由當(dāng)前主機(jī)系統(tǒng)決定。比如:Intel x86和AMD64(x86-64)使用小字節(jié)序; Motorola 68000和 PowerPC G5使用大字節(jié)序。ARM和Intel安騰支持切換字節(jié)序。可以使用sys.byteorder查看當(dāng)前系統(tǒng)的字節(jié)順序。
本地大小(Size)和對(duì)齊(Alignment)是由c編譯器的sizeof表達(dá)式確定的。它與本地字節(jié)順序?qū)?yīng)。
標(biāo)準(zhǔn)大小由格式符確定,下面會(huì)講各個(gè)格式的標(biāo)準(zhǔn)大小。
示例:
import struct import binasciivalues = (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('占用字節(jié): ', s.size)print('打包結(jié)果: ', binascii.hexlify(packed_data))print('解包結(jié)果: ', s.unpack(packed_data))# output 原始值 : (1, b'ab', 2.7)格式符 : b'@ I 2s f' for native, native 占用字節(jié): 12 打包結(jié)果: b'0100000061620000cdcc2c40' 解包結(jié)果: (1, b'ab', 2.700000047683716)格式符 : b'= I 2s f' for native, standard 占用字節(jié): 10 打包結(jié)果: b'010000006162cdcc2c40' 解包結(jié)果: (1, b'ab', 2.700000047683716)格式符 : b'< I 2s f' for little-endian 占用字節(jié): 10 打包結(jié)果: b'010000006162cdcc2c40' 解包結(jié)果: (1, b'ab', 2.700000047683716)格式符 : b'> I 2s f' for big-endian 占用字節(jié): 10 打包結(jié)果: b'000000016162402ccccd' 解包結(jié)果: (1, b'ab', 2.700000047683716)格式符 : b'! I 2s f' for network 占用字節(jié): 10 打包結(jié)果: b'000000016162402ccccd' 解包結(jié)果: (1, b'ab', 2.700000047683716)4. 格式符
格式符對(duì)照表如下:
5. 緩沖區(qū)
將數(shù)據(jù)打包成二進(jìn)制通常是用在對(duì)性能要求很高的場(chǎng)景。
在這類場(chǎng)景中可以通過避免為每個(gè)打包結(jié)構(gòu)分配新緩沖區(qū)的開銷來(lái)優(yōu)化。
pack_into()和unpack_from()方法支持直接寫入預(yù)先分配的緩沖區(qū)。
''' 遇到問題沒人解答?小編創(chuàng)建了一個(gè)Python學(xué)習(xí)交流QQ群:531509025 尋找有志同道合的小伙伴,互幫互助,群里還有不錯(cuò)的視頻學(xué)習(xí)教程和PDF電子書! ''' import array import binascii import ctypes import structs = 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('打包結(jié)果寫入 :', 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' 打包結(jié)果寫入 : b'0100000061620000cdcc2c40' 解包 : (1, b'ab', 2.700000047683716)使用array模塊 原始值 : b'000000000000000000000000' 打包寫入 : b'0100000061620000cdcc2c40' 解包 : (1, b'ab', 2.700000047683716)總結(jié)
以上是生活随笔為你收集整理的Python基础教程— Struct模块的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Django中六个常用的自定义装饰器
- 下一篇: python赋值、深浅拷贝