struct.unpack()需要具有特定格式模式的bytes对象的错误长度

时间:2017-12-12 13:42:22

标签: python format unpack

我试图使用' BQ'来解码字节对象。 Python 3.6.2上的格式(即unsigned char + unsigned long),长度应该是9个字节,但是struct.unpack得到一个错误,要求更多的字节:

In [96]: struct.unpack('BQ',bytesObj)
---------------------------------------------------------------------------
error                                     Traceback (most recent call last)
<ipython-input-96-667267f631a1> in <module>()
----> 1 struct.unpack('BQ',bytesObj)

error: unpack requires a bytes object of length 16

当我将格式说明符的顺序更改为&#39; QB&#39;时,它并不会抱怨长度,尽管它应该是相同的:

In [97]: struct.unpack('QB',bytesObj)
Out[97]: (35184770581765, 0)

但是当我更换B&#39; B&#39; for&#39; f&#39;,这应该增加3个字节所需的长度,但错误保持不变:

In [98]: struct.unpack('fQ',bytesObj)
---------------------------------------------------------------------------
error                                     Traceback (most recent call last)
<ipython-input-98-c3792c78fd43> in <module>()
----> 1 struct.unpack('fQ',bytesObj)

error: unpack requires a bytes object of length 16

In [99]: struct.unpack('Qf',bytesObj)
---------------------------------------------------------------------------
error                                     Traceback (most recent call last)
<ipython-input-99-78065617d606> in <module>()
----> 1 struct.unpack('Qf',bytesObj)

error: unpack requires a bytes object of length 12

无论我之前使用过哪种格式,Q&#39;,总是会出现相同的错误,要求长度为16.只有当&#没有前面的格式时才会正常工作39; Q&#39;

我错过了什么吗?

1 个答案:

答案 0 :(得分:1)

从9到16字节的跳转发生是因为Python添加了打包字节以确保结构中的元素在与C中相同的边界上对齐。

manual的第7.3节对此进行了解释。

q格式元素(long long)和Q格式元素(unsigned long long)被强制在8字节边界上对齐STARTING。在q / Q之前的任何元素之后添加填充字节以确保这一点。

运行以下代码显示了这一点:

from struct import *

print "QB: " + str(calcsize ('QB'))
bytesObj = pack('QB', 1, 2)
print unpack('QB', bytesObj)

print "BQ: " + str(calcsize ('BQ'))
bytesObj = pack('BQ', 1, 2)
print unpack('BQ', bytesObj)

print "qB: " + str(calcsize ('qB'))
bytesObj = pack('qB', 1, 2)
print unpack('qB', bytesObj)

print "Bq: " + str(calcsize ('Bq'))
bytesObj = pack('Bq', 1, 2)
print unpack('Bq', bytesObj)

print "Qf: " + str(calcsize ('Qf'))
bytesObj = pack('Qf', 1, 2.0)
print unpack('Qf', bytesObj)

print "fQ: " + str(calcsize ('fQ'))
bytesObj = pack('fQ', 1.0, 2)
print unpack('fQ', bytesObj)

这给出了以下输出:

QB: 9
(1, 2)
BQ: 16
(1, 2)
qB: 9
(1, 2)
Bq: 16
(1, 2)
Qf: 12
(1, 2.0)
fQ: 16
(1.0, 2)

希望这有帮助。

(编辑):另外,正如OP所指出的,这个默认行为可以被覆盖;请参阅下面评论中的链接。