如何在Python中正确处理八位字节中的4位数据
我正在写一个应用程序,用来解析某些网络数据包。一个数据包的字段里包含了协议的版本号,这个版本号用一个字节表示,其中高4位是“主版本号”,低4位是“次版本号”。现在我正在用以下方式来解析这些版本号,但我在想有没有更好看或者更符合Python风格的方法来做这件事:
v = ord(data[17])
major = (v & int('11110000',2) ) >> 4
minor = v & int('00001111',2)
4 个回答
1
用字面量代替调用 int
会更整洁。比如,你可以使用二进制字面量或十六进制字面量:
major = (v & 0xf0) >> 4
minor = (v & 0x0f)
二进制字面量只适用于 Python 2.6 或更高版本,格式是 0b11110000
。如果你使用的是 Python 2.6 或更高版本,可能想看看 bytearray
类型,因为它可以让你把数据当作二进制来处理,这样就不需要调用 ord
了。
如果你在解析二进制数据时发现需要进行很多位操作,可能想尝试一些更通用的解决方案,因为有一些第三方模块专门处理这个问题。其中一个是 hachoir(编辑:已删除无效链接 1/2023),还有一个更底层的选择是 bitstring(编辑:已删除无效链接 1/2023)(这是我写的)。在这种情况下,你的解析可能会变成这样:
major, minor = data.readlist('uint:4, uint:4')
如果你需要进行很多这样的读取,这样的方式会更容易管理。
2
给函数起个好名字总是个不错的主意,这样可以把那些复杂和不相关的内容隐藏起来。这样一来,处理细节的代码就集中在一些小的、容易验证正确的函数里,而更高层的代码则可以直接说明这些细节处理的目的。
def high_nibble(byte):
"""Get 4 high order bits from a byte."""
return (byte >> 4) & 0xF
def low_nibble(byte):
"""Get 4 low order bits from a byte."""
return byte & 0xF
def parse_version(version_byte):
"""Get the major-minor version tuple from the version byte."""
return high_nibble(version_byte), low_nibble(version_byte)
major, minor = parse_version(version_byte)
3
你可以这样写二进制数字,比如0b1111000
不过对于你的例子,我可能会用十六进制来表示
v = ord(data[17])
major = (v & 0xF0) >> 4
minor = (v & 0x0F)
你可能还想使用struct模块来把数据包拆分成不同的部分