Python中的结构体和解包

4 投票
2 回答
1264 浏览
提问于 2025-04-18 06:25

我一直在努力理解解包是怎么回事。更具体地说,文档中的这个例子让我最困惑,因为我输入的内容完全一样,但输出却不一样。https://docs.python.org/2/library/struct.html#struct-examples

>>> from struct import *
>>> pack('hhl', 1, 2, 3)
'\x00\x01\x00\x02\x00\x00\x00\x03'
>>> unpack('hhl', '\x00\x01\x00\x02\x00\x00\x00\x03')
(1, 2, 3)
>>> calcsize('hhl')
8

8个字节的大小我能理解,但当我用calcsize('hhl')时,它返回的是16。把pack('hhl', 1, 2, 3)的结果存到一个变量里,然后解包是没问题的,但用十六进制值就不行。我收到的错误是“unpack需要一个长度为16的字符串参数”,你知道问题出在哪里吗?谢谢

2 个回答

1

如果你说的是像 '0001000200000003' 这样的十六进制字符串,你需要先用 binascii.unhexlify(或者 binascii.a2b_hex)来进行解码。

>>> import struct
>>> import binascii
>>> struct.unpack('>hhl', binascii.unhexlify('0001000200000003'))
(1, 2, 3)
2

这是因为当你执行:

>>> pack('hhl', 1, 2, 3)
'\x00\x01\x00\x02\x00\x00\x00\x03'

它并不是返回一个包含 [ \, x, 0, ...] 的字符串,而是返回一个字节数组,里面包含了每个以十六进制表示的数字:

>>> pack('hhl', 1, 2, 3)[0]
'\x00'

所以,当你在做:

>>> unpack('hhl', '\x00\x01\x00\x02\x00\x00\x00\x03')

实际上你是在尝试解包一个字符串,就像我之前说的那样。而如果你这样做:

>>> s = pack('hhl', 1, 2, 3)
'\x00\x01\x00\x02\x00\x00\x00\x03'
>>> unpack('hhl', s)
(1, 2, 3)

那就能按预期工作了。

现在正如 @falstru 所说,将一个包含十六进制的字符串转换成结构体可以理解的字节数组的方法是使用 binascii.unhexlify,这个方法会处理字节序和转换。你也可以自己手动完成这个过程:

>>> unpack('hhl', str(bytearray([1,0,2,0,0,0,0,0,3,0,0,0,0,0,0,0])))
(1, 2, 3)

撰写回答