对Python中的字节感到困惑

时间:2012-02-11 14:42:34

标签: python binary-data

我最近开始使用Python解析二进制数据的活动,但我对Python处理“byte”项的方式感到困惑。以...为例以下翻译对话:

>>> f = open('somefile.gz', 'rb')
>>> f
<open file 'textfile.gz', mode 'rb' at 0xb77f4d88>
>>> bytes = f.read()
>>> bytes[0]
'\x1f'
>>> len(bytes[0])
1
>>> int(bytes[0])  <---- calling __str__ automatically on bytes[0] ?
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '\x1f'

上面的会话显示bytes [0]的大小为1个字节,但__str__表示是十六进制的。不用担心,但是当我尝试将字节[0]视为单个字节时,我会得到时髦的行为。

如果我想基于某些规范解析/解释二进制流,其中规范包括十六进制,二进制和十进制的表示,我将如何去做。

例如将是“前两个字节为\xbeef,下一个是十进制8后跟一个打包位字段,其中每个字节的8位代表一些标志?我想有几个模块输出那使得这项任务很容易,但我想从头开始。

我见过对struct模块的引用但是没有引入新模块就无法直接检查读取的字节数?像bytes[0] == 0xbeef

这样的东西

有人可以帮我解决一下人们通常使用Python解析符合规范的二进制数据吗?感谢。

2 个答案:

答案 0 :(得分:5)

你正在使用Python 2.x.在Python 3.0之前,读取文件,甚至是二进制文件,都会返回一个字符串。你所谓的“字节”对象实际上是一个字符串。像“bytes [0]”一样索引到字符串中只返回1个字符的字符串。

结构模块可能最适合你想要的东西,但如果你真的想要,你可以不用它来做你想要的:

“像bytes [0] == 0xbeef?”

这不起作用,因为0xbeef是一个双字节序列,但bytes [0]只是一个字节。你可以这样做:

bytes[0:2] == b'\xbe\xef'

在Python 3.x中,事情比你期望的更有效。读取二进制文件会返回一个bytes对象,其行为类似于1字节无符号整数序列,而不是字符串。

答案 1 :(得分:2)

如果要解析二进制数据,请查看struct模块。以下是doc中的示例:

>>> from struct import *
>>> pack('hhl', 1, 2, 3)
'\x00\x01\x00\x02\x00\x00\x00\x03'
>>> unpack('hhl', '\x00\x01\x00\x02\x00\x00\x00\x03')
(1, 2, 3)
>>> calcsize('hhl')
8

详细了解unpack:)

因此,如果您想将前2个字节作为无符号短路读取,并使用0xbeef进行测试:

struct.unpack('H', bytes[0:2]) == 0xbeef