struct模块怎么在Python项目中使用

这篇文章给大家介绍struct模块怎么在Python项目中使用,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

模块函数和Struct类

struct模块怎么在Python项目中使用

它除了提供一个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库的字节顺序来编码的。格式化字符串的第一个字符可以用来表示填充数据的字节顺序、大小和对齐方式,如下表所描述的:

CharacterByte orderSizeAlignment
@本地本地本地
=本地standardnone
<little-endian(小字节序)standardnone
>big-endian(大字节序)standardnone
!network (= big-endian)standardnone

如果格式符中没有设置这些,那么默认将使用 @。

本地字节顺序是指字节顺序是由当前主机系统决定。比如: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)

格式符

格式符对照表如下:

FormatC TypePython typeStandard sizeNotes
xpad byteno value
ccharbytes of length 11
bsigned charinteger1(1),(3)
Bunsigned charinteger1(3)
?_Boolbool1(1)
hshortinteger2(3)
Hunsigned shortinteger2(3)
iintinteger4(3)
Iunsigned intinteger4(3)
llonginteger4(3)
Lunsigned longinteger4(3)
qlong longinteger8(2), (3)
Qunsigned long longinteger8(2), (3)
nssize_tinteger(4)
Nsize_tinteger(4)
ffloatfloat4(5)
ddoublefloat8(5)
schar[]bytes
pchar[]bytes
Pvoid *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项目中使用就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

发布于 2021-03-17 20:55:06
收藏
分享
海报
0 条评论
162
上一篇:怎么在python3中替换python2的cmp函数 下一篇:如何在Python中使用threading和multiprocessing多线程模块
目录

    推荐阅读

    0 条评论

    本站已关闭游客评论,请登录或者注册后再评论吧~

    忘记密码?

    图形验证码