Python结构模块长度的差异

时间:2016-03-18 12:26:20

标签: python

我正在尝试使用Python的struct模块解码来自GPS系统的一些二进制头文件。我有两种类型的标题,长和短,我有一个阅读下面每一个的例子:

import struct
import binascii

packed_data_short = binascii.unhexlify('aa44132845013b078575e40c')
packed_data_long = binascii.unhexlify('aa44121ca20200603400000079783b07bea9bd0c00000000cc5dfa33')

print packed_data_short
print len(packed_data_short)

sS = struct.Struct('c c c B H H L')

unpacked_data_short = sS.unpack(packed_data_short)
print 'Unpacked Values:', unpacked_data_short

print ''

print packed_data_long
print len(packed_data_long)

sL = struct.Struct('c c c B H c b H H b c H L L H H')

unpacked_data_long = sL.unpack(packed_data_long)
print 'Unpacked Values:', unpacked_data_long

在这两种情况下,我得到了我期望的长度 - 短标头为12个字节,长标头为28个字节。此外,所有字段都正确显示(据我所知,对于旧数据)是合理的值。到目前为止一切都很好。

我把它移到另一台计算机上(运行不同版本的Python - 2.7.6而不是2.7.11)并且我使用calcsize得到不同的结构长度,并且尝试传递它的长度会出错我已经计算了,而另一个版本是满意的。现在短标头需要16个字节,而长标签需要36个字节。

如果我传递的金额较大,则要求查找大部分记录,直到“L”记录为止。在长示例中,第一个是预期的,但第二个应该只是0,不正确,因此后面的两个字段也是不正确的。根据函数想要的字节数,我注意到每个“L”都是4,实际上只是运行struct.calcsize('L')我得到的长度是2.7.6,4是2.7.11 。这至少缩小了问题所在,但我不明白为什么会发生这种情况。

目前我正在将第二台计算机更新为Python 2.7.11(一旦我拥有它就会更新),但我在结构文档中找不到任何可能表明已对此进行更改的内容。有没有我明显错过的或者这只是一个版本问题?

我所指的文档是here

编辑:关于OS的评论 - 一个是Windows 7的64位版本(按预期工作的那个),第二个是64位版本的Ubuntu 14.04。

1 个答案:

答案 0 :(得分:6)

这不是一个错误;见struct documentation

  

请注意

     

默认情况下,打包给定C结构的结果包括填充字节   为了保持所涉及的C类型的正确对齐;   类似地,在拆包时考虑对齐。这个   选择行为,以便打包结构的字节对应   完全对应于相应C结构的内存布局。至   处理与平台无关的数据格式或省略隐式填充字节,   使用标准大小和对齐而不是原生大小和对齐方式:   见Byte Order, Size, and Alignment for details.

要解码来自该GPS设备的数据,您需要在7.3.2.1. Byte Order, Size, and Alignment中所述的格式字符串中使用<>。因为你让它在另一台机器上运行,我认为数据是小端格式的,如果你使用它可以移植它

sS = struct.Struct('<cccBHHL')
sL = struct.Struct('<cccBHcbHHbcHLLHH')

其大小始终为

>>> sS.size
12
>>> sL.size
28

他们为什么不同?您正在使用的原始计算机是Windows计算机或32位计算机,而远程计算机是64位* nix。在本机大小中,L表示C编译器的类型unsigned long。在32位Unixen和所有Windows版本中,这是32位宽。

在64位Unix中,x86上的标准ABI为LP64,这意味着long和指针是64位宽。但是,Windows uses LLP64;那里只有long long是64位;原因是很多代码甚至Windows API本身长期依赖long正好是32位。

如果存在<标志,则LI都始终保证为32位。其他字段说明符没有问题,因为它们的大小在所有x86平台和操作系统上保持不变。