struct模块怎么在Python项目中使用
这篇文章给大家介绍struct模块怎么在Python项目中使用,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。
模块函数和Struct类
它除了提供一个Struct类之外,还有许多模块级的函数用于处理结构化的值。这里有个格式符(Format specifiers)的概念,是指从字符串格式转换为已编译的表示形式,类似于正则表达式的处理方式。通常实例化Struct类,调用类方法来完成转换,比直接调用模块函数有效的多。下面的例子都是使用Struct类。
Packing(打包)和Unpacking(解包)
Struct支持将数据packing(打包)成字符串,并能从字符串中逆向unpacking(解压)出数据。
在本例中,格式指定器(specifier)需要一个整型或长整型,一个两个字节的string,和一个浮点数。格式符中的空格用于分隔各个指示器(indicators),在编译格式时会被忽略。
importstruct importbinascii values=(1,'ab'.encode('utf-8'),2.7) s=struct.Struct('I2sf') 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()方法解包。
importstruct importbinascii packed_data=binascii.unhexlify(b'0100000061620000cdcc2c40') s=struct.Struct('I2sf') 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表达式确定的。它与本地字节顺序对应。
标准大小由格式符确定,下面会讲各个格式的标准大小。
示例:
importstruct importbinascii values=(1,'ab'.encode('utf-8'),2.7) print('原始值:',values) endianness=[ ('@','native,native'), ('=','native,standard'), ('<','little-endian'), ('>','big-endian'), ('!','network'), ] forcode,nameinendianness: s=struct.Struct(code+'I2sf') 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()方法支持直接写入预先分配的缓冲区。
importarray importbinascii importctypes importstruct s=struct.Struct('I2sf') values=(1,'ab'.encode('utf-8'),2.7) print('原始值:',values) print() print('使用ctypes模块stringbuffer') 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)
关于struct模块怎么在Python项目中使用就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
推荐阅读
-
Python中怎么动态声明变量赋值
这篇文章将为大家详细讲解有关Python中怎么动态声明变量赋值,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文...
-
python中变量的存储原理是什么
-
Python中怎么引用传递变量赋值
这篇文章将为大家详细讲解有关Python中怎么引用传递变量赋值,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文...
-
python中怎么获取程序执行文件路径
python中怎么获取程序执行文件路径,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的...
-
Python中如何获取文件系统的使用率
Python中如何获取文件系统的使用率,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴...
-
Python中怎么获取文件的创建和修改时间
这篇文章将为大家详细讲解有关Python中怎么获取文件的创建和修改时间,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读...
-
python中怎么获取依赖包
今天就跟大家聊聊有关python中怎么获取依赖包,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据...
-
python怎么实现批量文件加密功能
-
python中怎么实现threading线程同步
小编给大家分享一下python中怎么实现threading线程同步,希望大家阅读完这篇文章之后都有所收获,下面让我们一起去探讨吧!...
-
python下thread模块创建线程的方法
本篇内容介绍了“python下thread模块创建线程的方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来...