【问题标题】:Correct interpretation of hex byte, convert it to float正确解释十六进制字节,将其转换为浮点数
【发布时间】:2016-12-16 21:08:37
【问题描述】:

我目前正在尝试通过 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 转换为浮点数。但是因为它显示的是非十六进制数字,所以我不能这样做。

【问题讨论】:

  • 为什么需要这些字节作为十六进制数字?您是在尝试调试代码并想知道字节的内容为十六进制数字,还是需要将此数据显示给程序的用户?您在此处查看调试信息,而不是最终用户友好的表示。
  • 如果您只想将这些字节转换为整数,请查看int.from_bytes 方法。
  • 您打算如何将十六进制数字转换为浮点数?您通常会采用字节值。这些值都还在。

标签: python python-3.x hex binascii


【解决方案1】:

Ce/ 也是字节;它们是 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 等。

输出是bytes 对象的默认repr() 输出。它不能改变。如果您需要不同的输出,则必须编写自己的代码。

您可以使用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

这是一个带有\x 和十六进制数字作为字符的str 对象。

请注意,这只是显示值。价值没有改变;字节都在那里,但是你显示它们。如果您需要将 4 个字节转换为浮点数,则只需将这 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,)

【讨论】:

    【解决方案2】:

    您可以使用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']
    

    【讨论】:

      猜你喜欢
      • 2014-03-01
      • 2010-12-08
      • 1970-01-01
      • 2016-06-02
      • 1970-01-01
      • 2020-10-17
      • 2016-06-01
      相关资源
      最近更新 更多