Python struct.Struct.size 返回意外值

Python struct.Struct.size returning unexpected value

我正在使用 Python 将一些文件转换为二进制格式,但我 运行 变成了一个奇怪的圈套。

问题

代码

import struct
s = struct.Struct('Bffffff')
print s.size

结果

28

显然预期的大小是 25,但它似乎将第一个字节 (B) 解释为某种 4 字节整数。它还将写出一个 4 字节整数而不是一个字节。

解决方法

存在变通方法,即将 B 分离成单独的 struct,如下所示:

代码

import struct
s1 = struct.Struct('B')
s2 = struct.Struct('ffffff')
print s1.size + s2.size

结果

25

对这种行为有什么解释吗?

来自docs

Padding is only automatically added between successive structure members. No padding is added at the beginning or the end of the encoded struct.

如果你测试

>>> import struct
>>> s1 = struct.Struct('B')
>>> print s1.size
1
>>> s1 = struct.Struct('f')
>>> print s1.size
4

所以当你添加它时它是 25 ...但是反过来,B 是 1 其余的是 4 所以它会被填充以使其 4 因此答案是 28 考虑这个例子

>>> s1 = struct.Struct('Bf')
>>> print s1.size
8

同样这里 B1 并填充 3f4 所以最后它得出 8 这是不出所料。

如前所述here要覆盖它,您将不得不使用非本机方法

>>> s1 = struct.Struct('!Bf')
>>> print s1.size
5

No padding is added when using non-native size and alignment, e.g. with ‘<’, ‘>’, ‘=’, and ‘!’.

除非您为字节顺序、对齐方式指定任何字符,否则struct使用本机字节顺序、对齐方式(@);这会导致填充。

通过显式指定字节顺序,你可以得到你想要的:

>>> struct.Struct('!Bffffff').size  # network byte order
25
>>> struct.Struct('=Bffffff').size  # native byte order, no alignment.
25
>>> struct.Struct('>Bffffff').size  # big endian
25
>>> struct.Struct('<Bffffff').size  # little endian
25
>>> struct.Struct('@Bffffff').size  # native byte order, alignment. (+ native size)
28