我目前正在尝试通过RS485连接电表。 到目前为止它工作得很好,除了我在读取仪表在RS485线路上写回的内容时遇到了问题。
我知道电表的数据是正确的,因为我可以用Docklight和制造商的内部程序读取它。
所以我唯一的问题是我要回来的十六进制字节的转换。
我正在接收
>>> b'\x01\x03\x04Ce/\xec\xe2'
这应该是8或9个十六进制字节。 我希望得到像
这样的东西>>> b'\x01\x03\x04\x43\x67\x81\xEC\x43\x68'
问题似乎是python在" ASCII"中解释它。因为非十六进制数字,它可以进一步转换它。 我得到的错误是
>>> binascii.Error: Non-hexadecimal digit found`
当我从另一边看它时的等价物。 我发送
>>> data=bytearray([0x01,0x03,0x4A,0x38,0x00,0x02,0x53,0xDE])
显示为
>>> bytearray(b'\x01\x03J8\x00\x02S\xde')
我打印时
那么我怎么能告诉python-3我想看到8个十六进制字节而不是他自动制作的一些解释呢?我相信,一旦你知道在哪里寻找,我就会失去一些非常容易的东西。
我想将字节4,5,6,7转换为float。但由于它向我显示非十六进制数字,我不能这样做。
答案 0 :(得分:1)
C
,e
和/
也是字节;它们是 ASCII字符,因此不需要与\x..
十六进制转义一起显示。
您也不需要解码\x..
十六进制转义符,它们就是Python为您提供bytes
对象的调试表示的方式;每个字节显示为转义序列或可打印的ASCII字母。
同样的事情发生在你的这样的例子:
>>> b'\x01\x03\x04\x43\x67\x81\xEC\x43\x68'
b'\x01\x03\x04Cg\x81\xecCh'
这是完全相同的值,但\x68
是ASCII字母h
等。
输出是repr()
个对象的默认bytes
输出。它无法改变。如果您需要不同的输出,则必须编写自己的代码。
您可以使用binascii.hexlify()
函数将所有字节显示为十六进制,例如:
>>> import binascii
>>> binascii.hexlify(b'\x01\x03\x04\x43\x67\x81\xEC\x43\x68')
b'010304436781ec4368'
现在您有一个bytes
字符串,其中包含十六进制字符。或者您可以使用str.join()
函数将每个字节转换为十六进制,并以\x
文字为前缀:
>>> ''.join(r'\x{:02x}'.format(byte) for byte in b'\x01\x03\x04\x43\x67\x81\xEC\x43\x68')
'\ X01 \ X03 \ X04 \ X43 \ X67 \ X81 \ XEC \ X43 \ X68'
>>> print(''.join(r'\x{:02x}'.format(byte) for byte in b'\x01\x03\x04\x43\x67\x81\xEC\x43\x68'))
\x01\x03\x04\x43\x67\x81\xec\x43\x68
这是一个str
对象,\
,x
和十六进制数字作为字符。
请注意,这只是显示值。价值没有改变;这些字节都在那里,但是你显示它们。如果需要将4个字节转换为float,则只需转换这4个字节:
struct.unpack('f', yourbytes[4:]) # 4 bytes for C float in native order
这使用struct
module直接使用字节。不需要十六进制表示:
>>> import struct
>>> struct.unpack('f', b'\x01\x03\x04Ce/\xec\xe2'[:4])
(132.01173400878906,)
答案 1 :(得分:1)
您可以使用struct.unpack()
从数据中获取数字。这是方法:
In [171]: import struct
In [190]: b2
Out[190]: b'\x01\x03J8\x00\x02S\xde'
In [191]: struct.unpack('B'*len(b2), b2)
Out[191]: (1, 3, 74, 56, 0, 2, 83, 222)
In [192]: [*map(hex, struct.unpack('B'*len(b2), b2))]
Out[192]: ['0x1', '0x3', '0x4a', '0x38', '0x0', '0x2', '0x53', '0xde']