struct.unpack() 需要来自具有特定格式模式的字节对象的错误长度
struct.unpack() requires wrong length from bytes object with specific format pattern
我正在尝试在 Python 3.6.2 上解码具有 'BQ' 格式(即 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
当我将格式说明符的顺序更改为 'QB' 时,它不会抱怨长度,尽管它应该是相同的:
In [97]: struct.unpack('QB',bytesObj)
Out[97]: (35184770581765, 0)
但是当我将 'B' 替换为 'f' 时,它变得更加奇怪,这应该增加 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' 之前使用哪种格式,它总是得到相同的错误,要求长度为 16。它似乎只有在没有 'Q' 的先行格式时才能正常工作。
我是不是漏掉了什么?
从 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)
希望对您有所帮助。
(Edit):此外,正如 OP 所指出的,可以覆盖此默认行为;请参阅下面评论中的 link。
我正在尝试在 Python 3.6.2 上解码具有 'BQ' 格式(即 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
当我将格式说明符的顺序更改为 'QB' 时,它不会抱怨长度,尽管它应该是相同的:
In [97]: struct.unpack('QB',bytesObj)
Out[97]: (35184770581765, 0)
但是当我将 'B' 替换为 'f' 时,它变得更加奇怪,这应该增加 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' 之前使用哪种格式,它总是得到相同的错误,要求长度为 16。它似乎只有在没有 'Q' 的先行格式时才能正常工作。
我是不是漏掉了什么?
从 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)
希望对您有所帮助。
(Edit):此外,正如 OP 所指出的,可以覆盖此默认行为;请参阅下面评论中的 link。