精心制作的十六进制字符串在字符串格式中正确,一旦传递给 unhexlify() 就会出现格式错误

Crafted hex string correct in string format, malforms once passed to unhexlify()

def craft_integration(xintegration_time):

 integration_time = xintegration_time
 integration_time_str = str(integration_time)
 integration_time_str = integration_time_str.encode('utf-8')
 integration_time_hex = integration_time_str.hex()

 return integration_time_hex

def send_set_integration(xtime):

 int_time_hex = decoder_crafter.craft_integration(xtime)

 set_hex = "c1c000000000000010001100000000000000000000000004"+int_time_hex+"1400000000000000000000000000000000000000c5c4c3c2"
 set_hex = str(set_hex)
 print(set_hex)
 set_hex = unhexlify(set_hex)

例如,输入'1000'。 用 craft_integration() 变成 31303030。 然后将其插入到默认的十六进制字符串中。

输出为:

c1c00000000000001000110000000000000000000000000431303030140000000000000000000000000000000000000c5c4c3c2

当使用 unhexlify() 时,输出为:

b'\xc1\xc0\x00\x00\x00\x00\x00\x00\x10\x00\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x041000\x14\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xc5\xc4\xc3\xc2'

\x041000 是 \x04 和 1000 的结合,它是 原始 输入值,而不是转换后的值。

为什么会这样?

事实上,您所拥有的只是您想要的值被 bytes.__repr__ 的默认实现渲染到一个表单中,您没有预料到它对您想要的东西没有帮助。

从更基本的层面开始:在 Python 中,bytes 类型中的任何元素(好吧,任何 "byte",即一组 8 位)通常是以二进制形式存储在机器某处的原始数字表示形式。为了 "print" 将它们输出到控制台供人类使用,必须将其转换为控制台可以解释的形式,以便可以使用正确的字形来表示基础值。对于许多值,例如 0(或二进制的 00000000),Python 将使用 \x00 来表示。 \ 是开始转义序列的转义字符,后面的 x 表示转义序列后跟 2 个十六进制字符,将这两个字符与整个序列组合将形成使用四个字符表示该单个字节。同样对于 255,在二进制中将是 11111111,作为 bytes 类型的一部分的相同值将被编码为 \xff.

现在有例外 - 如果给定值落在 ASCII range, and that it in the range of printable characters 内,表示将改为相应的 ASCII 字符。因此,在十六进制 30(十进制 48)的情况下,将其呈现为 bytes 类型的一部分将显示 0 而不是 \x30,如0是对应的可打印字符。

因此,对于您的情况,以 b'\x041000' 形式在控制台中打印出的 bytes 表示实际上并不是一个很大的 \x 值,因为 \x 转义序列仅适用于恰好两个后续字符 - 所有后续字符(即 1000)实际上都使用可打印字符表示,否则将表示为 \x31\x30\x30\x30.

对于那些不介意使用字节的十进制表示形式的人,还有另一种方法可用 - 只需将 bytes 转换为 bytearray,然后转换为 list。我们以两个nul字节(b'\x00\x00')为例:

>>> list(bytearray(b'\x00\x00'))
[0, 0]

很明显,这两个 nul 字节将对应两个零值。现在尝试使用令人困惑的 b'\x04\x31\x30\x30\x30' 渲染成 b'\x041000':

>>> list(bytearray(b'\x041000'))
[4, 49, 48, 48, 48]

我们可以注意到,它实际上是 5 个字节,在 5 个元素的列表中用相应的十进制数字呈现。

通常很容易混淆实际值与计算机控制台上显示和可视化的值。不幸的是,我们使用的工具有时会加剧这种混乱,但作为程序员,我们应该理解这一点,并设法为我们工作的用户尽量减少这种混乱,因为这个例子表明,并不是每个人都有直觉 bytes 的某些表示可能而是表示为可打印的 ASCII。