Python/PySerial 字符串位操作
我正在使用PySerial(Python 2.7)从一个设备读取信息,代码是这样的:
buffer += ser.read(3)
现在我的buffer里有三个字节的数据(比如0xAE0259),它的类型是字符串。因为我刚开始学Python,所以我想找一种“Python风格”的方法来去掉最左边的部分(0xAE),然后把剩下的两个字节当成整数来处理。
我最开始想用位掩码:buffer &= 0xFFFF,但Python不允许我在字符串上使用位运算符。
我尝试把buffer转换成整数也失败了。后来我看到有个叫'bitstring模块'的东西,可以让我从BitArray中切割出一段位,但我觉得用这个来处理这个问题可能有点复杂了。
5 个回答
有两种简单的方法可以做到这一点。第一种方法是把你的缓冲区转换成十六进制整数,然后用位掩码来获取最后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
如果你只需要处理字节拆解,那么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]
你需要知道多字节类型是大端还是小端,以及它是有符号还是无符号。假设这两个字节是一个无符号的大端短整型,我会这样做:
>>> buf = '\xAE\x02\x59'
>>> from struct import unpack
>>> unpack('>BH', buf)
(174, 601)
'>'表示大端。'B'是第一个无符号字节,但我们不需要它。'H'表示一个无符号的短整型。