MicroPython调用binascii.hexlify处理列表元素报TypeError的原因
问题根因
这个报错本质是类型不匹配导致的:你看到的列表打印结果和实际存储的元素类型不一致,data_raw[0]实际是0-255区间的整数,不是你以为的单字节bytes对象。
树莓派Pico对应的MicroPython rp2固件早期版本存在REPL显示bug:当列表中存储0-255范围的整数时,打印列表会把这类整数错误渲染为b'\xXX'格式的单字节bytes字面量,迷惑性极强。binascii.hexlify()仅接受实现了缓冲区协议的对象作为入参,包括bytes/bytearray/memoryview这类连续字节序列类型,传入整数时就会抛出TypeError: object with buffer protocol required。你直接写的b'\x02'是真实的长度为1的bytes对象,符合参数要求,所以可以正常运行。
验证方式
直接执行代码打印元素类型即可确认:
print(type(data_raw[0]))
如果输出为<class 'int'>,就和上述问题完全匹配。
这个问题通常出现在列表构造环节:绝大多数人是直接遍历bytes/bytearray类型的原始字节流,把遍历得到的元素直接追加到列表中——不管是MicroPython还是标准CPython,遍历字节序列、用单个下标取字节序列元素,拿到的返回值都是整数,不是单字节bytes对象:
# 错误构造示例 raw_buf = b'\x02\x88\x84\x80\x80' data_raw = [] for b in raw_buf: data_raw.append(b) # 此时data_raw内全是int类型,在有bug的固件里打印会显示为[b'\x02', b'\x88', b'\x84', b'\x80', b'\x80']
解决方案
根据你的实际场景选对应方案即可:
- 如果只需要把单个字节值转十六进制字符串,不需要调用
hexlify,直接用格式化方法性能更好:# 两种写法MicroPython均支持 hex_str = '%02x' % data_raw[0] hex_str = f"{data_raw[0]:02x}" - 如果必须使用
hexlify处理,把整数字节转为单字节bytes对象再传入:hex_str = binascii.hexlify(bytes([data_raw[0]])).decode() - 如果希望列表里直接存单字节bytes对象,在构造列表时就做类型转换:
raw_buf = b'\x02\x88\x84\x80\x80' data_raw = [] for b in raw_buf: data_raw.append(bytes([b]))
内容的提问来源于stack exchange,提问作者NicoCaldo
相关产品推荐
相关产品推荐

