将字节数组从 \xff 转换为 x0FF
我正在用Python 3写一段代码,目的是从心电图传感器读取数据。最终的代码需要把从传感器收到的数据包写入一个文件中。
这是我现在写的代码:
import serial
if __name__ == '__main__':
buffer = [0, 0, 0, 0, 0, 0]
f = open('dumpECG', 'w')
print("Hi")
ser = serial.Serial('/dev/ttyUSB0', 115200)
while 1 == 1:
while ser.inWaiting() > 6:
buf = ser.read()
if buf > b'\xf7':
if buf == b'\xfd':
1 == 1
else:
buffer[0] = buf
if ser.isOpen():
buffer[1] = ser.read()
if buffer[0] == b'\xf8':
temp = (ord(buffer[1]) >> 4) + 2
if temp < 11:
for i in range(2, int(temp), 1):
if ser.isOpen():
buffer[i] = ser.read()
print(buffer)
data = ''.join(str(e) for e in buffer)
data = map(hex, map(ord, data))
f.write(''.join(data))
f.write("\n")
elif buffer[0] == b'\xfe':
temp = (ord(buffer[1]) >> 4) + 2
if temp < 8:
for i in range(2, int(temp), 1):
if ser.isOpen():
buffer[i] = ser.read()
print(buffer)
f.write(''.join(str(e) for e in buffer))
f.write("\n")
elif buffer[0] == b'\xf9' or buffer[0] == b'\xfa':
if ser.isOpen():
buffer[2] = ser.read()
print(buffer)
f.write(''.join(str(e) for e in buffer))
f.write("\n")
elif buffer[0] == b'\xfc':
for i in range(2, int(6), 1):
if ser.isOpen():
buffer[i] = ser.read()
f.write(''.join(str(e) for e in buffer))
f.write("\n")
作为示例数据,当我第一次打印(buffer)时,buffer里面的内容是:"[b'\xf8', b'8', b'\x80', b'\x80', b'\x80', 0]",我需要把它写成文件里的"0xF8, 0x38, 0x80, 0x80, 0x80, 0"。
我尝试过这样做:
data = ''.join(str(e) for e in buffer)
data = map(hex, map(ord, data))
但是它把所有字符都转换了,而不是我想要的数值。
1 个回答
1
你现在有这样的内容:
"[b'\xf8', b'8', b'\x80', b'\x80', b'\x80', 0]"
而你想要的是这样的:
"0xF8, 0x38, 0x80, 0x80, 0x80, 0"
(我假设你其实想要的是 0x38
,而不是 0x08
,因为 b'8'
对应的是 b'\x38'
,而不是 b'\x08'
。如果我理解错了,你需要解释一下你的规则……)
首先要注意的是,这显然是 Python 的 repr
函数生成的输出,因为没有其他常见的方法会给你这些以 b
开头的字符串。如果可能的话,最好是修改生成这些字符串的代码,让它直接传递列表(如果在 Python 内部)或者使用一些标准、安全、可靠的交换格式,比如 JSON,而不是直接打印 repr
的结果。但如果你不能改变这一点,那么反向操作的方法就是使用 ast.literal_eval
:
>>> ast.literal_eval(buffer)
[b'\xf8', b'8', b'\x80', b'\x80', b'\x80', 0]
接下来,这些值中有些是单字节的 bytes
对象,有些是数字。看起来你想保留数字不变,但把字节转换成十六进制数字。所以,我们需要对每种类型做不同的处理。
那么我们该如何处理每种类型呢?对于 bytes
,我们需要调用 ord
(或者直接用 [0]
),然后再用 hex
,这正是你想做的。但对于 int
,我们只需要调用 str
。所以:
>>> [hex(ord(b)) if isinstance(b, bytes) else str(b)
... for b in ast.literal_eval(buffer)]
['0XF8', '0X38', '0X80', '0X80', '0X80', '0']
现在我们只需要把它们连接起来:
>>> ', '.join(hex(ord(b)) if isinstance(b, bytes) else str(b)
... for b in ast.literal_eval(buffer))
'0xf8, 0x38, 0x80, 0x80, 0x80, 0'
如果你真的需要字母的十六进制数字是大写的,hex
是做不到的,所以:
>>> ', '.join('0x{:2X}'.format(ord(b)) if isinstance(b, bytes) else str(b)
... for b in ast.literal_eval(buffer))
'0xF8, 0x38, 0x80, 0x80, 0x80, 0'