在Python中进行位字段操作的最佳方法是什么?
我正在研究通过UDP传输的MPEG传输流协议,里面有一些奇怪的位域(比如长度为13位)。我正在使用“struct”库来进行大致的解包,但有没有简单的方法可以直接“获取接下来的13位”,而不是手动调整位操作?我希望能有类似C语言处理位域的方式(但不想回到C语言)。
有什么建议吗?
2 个回答
28
bitstring模块就是为了解决这个问题而设计的。它可以让你用比特(也就是二进制的0和1)作为基本单位来读取、修改和构建数据。最新的版本支持Python 2.6及以上(包括Python 3),而1.0版本则支持Python 2.4和2.5。
一个相关的例子是,这段代码可以从传输流中去掉所有的空数据包(可能还用到了你的13位字段):
from bitstring import Bits, BitStream
# Opening from a file means that it won't be all read into memory
s = Bits(filename='test.ts')
outfile = open('test_nonull.ts', 'wb')
# Cut the stream into 188 byte packets
for packet in s.cut(188*8):
# Take a 13 bit slice and interpret as an unsigned integer
PID = packet[11:24].uint
# Write out the packet if the PID doesn't indicate a 'null' packet
if PID != 8191:
# The 'bytes' property converts back to a string.
outfile.write(packet.bytes)
这里还有另一个例子,展示了如何从比特流中读取数据:
# You can create from hex, binary, integers, strings, floats, files...
# This has a hex code followed by two 12 bit integers
s = BitStream('0x000001b3, uint:12=352, uint:12=288')
# Append some other bits
s += '0b11001, 0xff, int:5=-3'
# read back as 32 bits of hex, then two 12 bit unsigned integers
start_code, width, height = s.readlist('hex:32, 2*uint:12')
# Skip some bits then peek at next bit value
s.pos += 4
if s.peek(1):
flags = s.read(9)
你可以使用标准的切片语法在比特级别进行切片、删除、反转、覆盖等操作,还有查找、替换、分割等功能。不同的字节序(endianness)也得到了支持。
# Replace every '1' bit by 3 bits
s.replace('0b1', '0b001')
# Find all occurrences of a bit sequence
bitposlist = list(s.findall('0b01000'))
# Reverse bits in place
s.reverse()
完整的文档可以在这里找到。
9
这个问题经常被问到。以前我用过一个在ASPN Cookbook上的例子,效果不错。
还有一个详细的页面,上面列出了一个人希望从一个处理这类事情的模块中看到的各种需求。