Python struct.Struct.size返回意外值

时间:2015-02-08 11:56:09

标签: python struct

我使用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

这种行为有什么解释吗?

2 个答案:

答案 0 :(得分:6)

来自docs

  

填充仅在连续的结构成员之间自动添加。在编码结构的开头或结尾没有添加填充。

如果你测试

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

所以当你添加时它是25 ...但反过来说,B是1,其余的是4所以它将被填充以使其成为{{1}所以答案是4 考虑这个例子

28

此处>>> s1 = struct.Struct('Bf') >>> print s1.size 8 再次B并填充13f,因此最终达到4,这与预期一致

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

8
  

使用非原生大小和对齐时,不添加填充,例如使用'<','>','='和'!'。

答案 1 :(得分:4)

除非为字节顺序指定任何字符,否则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