Python/PySerial 字符串位操作

3 投票
5 回答
3669 浏览
提问于 2025-04-16 20:56

我正在使用PySerial(Python 2.7)从一个设备读取信息,代码是这样的:

buffer += ser.read(3)

现在我的buffer里有三个字节的数据(比如0xAE0259),它的类型是字符串。因为我刚开始学Python,所以我想找一种“Python风格”的方法来去掉最左边的部分(0xAE),然后把剩下的两个字节当成整数来处理。

我最开始想用位掩码:buffer &= 0xFFFF,但Python不允许我在字符串上使用位运算符。

我尝试把buffer转换成整数也失败了。后来我看到有个叫'bitstring模块'的东西,可以让我从BitArray中切割出一段位,但我觉得用这个来处理这个问题可能有点复杂了。

5 个回答

1

有两种简单的方法可以做到这一点。第一种方法是把你的缓冲区转换成十六进制整数,然后用位掩码来获取最后32位。第二种方法是使用切片操作符来获取最后4个字符,然后把剩下的部分当作十六进制整数来理解。

>>> buffer = 'AE0259'
>>> print int(buffer, 16) & 0xFFFF
601
>>> print int(buffer[-4:], 16) 
601

补充说明 - eryksun 给出了正确的答案,但我想更新我的例子,以便更贴近实际使用情况。

>>> buffer = '\xAE\x02\x59'
>>> # print the integer value of the last two binary "characters"
>>> print sum((ord(x) << i*8 for i,x in enumerate(buffer[:-2-1:-1])))
601
>>> # print the integer value all binary "characters" 
>>> # with a bitmask of the lower 32 digits
>>> print sum((ord(x) << i*8 for i,x in enumerate(buffer[::-1]))) & 0xFFFF
601
1

如果你只需要处理字节拆解,那么struct模块会很适合你(可以参考eryksun的回答),还有bytearray类型:

>>> ba = bytearray('\xae\x02\x59')

这让你可以在字节级别进行索引和切片操作。

>>> hex(ba[0])
'0xae'
>>> ba[1:3]
bytearray(b'\x02Y')

在将多个字节转换为整数时,这非常有帮助,但如果你的字节长度没有什么特别的,使用struct可能不会有太大差别。你把两个字节转换为整数的过程变成了:

>>> (ba[1] << 8) + ba[2]
601

你在评论中提到你想要一种通用的方法来进行位切片。很抱歉,目前没有这样的通用方法——你最好从字节数组的位移和掩码开始。这就是像bitstring这样的模块有用的原因(顺便说一下,我写了这个模块)——这样你就可以把那些繁琐且容易出错的事情交给别人来做!

>>> b = bitstring.Bits(ba)
>>> b[8:].uint
601
>>> b.unpack('hex:8, uint:16')
['ae', 601]
2

你需要知道多字节类型是大端还是小端,以及它是有符号还是无符号。假设这两个字节是一个无符号的大端短整型,我会这样做:

>>> buf = '\xAE\x02\x59'
>>> from struct import unpack
>>> unpack('>BH', buf)
(174, 601)

'>'表示大端。'B'是第一个无符号字节,但我们不需要它。'H'表示一个无符号的短整型。

撰写回答