Python uuid模块:UUID v4实例bytes属性解码疑问
关于Python UUID模块中bytes属性的疑问
我希望通过Python标准库的uuid模块生成UUID v4字符串,已知可以用str(uuid.uuid4())把UUID转成字符串,但想搞懂UUID类实例的bytes属性到底是什么意思。尝试解码这些字节时,要么得到奇怪的字符串,要么直接抛出异常。根据文档,UUID.bytes是包含六个整数字段的16字节大端序字节串,但解码后根本得不到str转换后的UUID,这是为什么?
>>> import uuid >>> my_uuid = uuid.uuid4() >>> str(my_uuid) '3f5017be-a314-4bb2-92c0-5135b47f8c45' >>> my_uuid.bytes.decode('latin1') '?P\x17¾£\x14K²\x92ÀQ5´\x7f\x8cE' >>> my_uuid.bytes.decode('utf-8', 'ignore') '?P\x17\x14KQ5\x7fE' >>> my_uuid.bytes.decode('utf-8') Traceback (most recent call last): File "<stdin>", line 1, in <module> UnicodeDecodeError: 'utf-8' codec can't decode byte 0xbe in position 3: invalid start byte >>> my_uuid.bytes.decode('utf-16') '倿븗ᒣ뉋삒㕑羴䖌' >>> my_uuid.bytes_le.decode('utf-16') 'ើ㽐ꌔ䮲삒㕑羴䖌'
解答
1. UUID.bytes是原始二进制数据,并非文本编码字节
UUID的bytes属性是UUID各字段按大端序(网络字节序)拼接的16字节原始二进制数据,它的设计目的是存储UUID的二进制形式,而非作为文本编码的字节流。
以你示例中的UUID 3f5017be-a314-4bb2-92c0-5135b47f8c45为例,它的bytes就是把各个十六进制段直接转成二进制后的拼接:
3f 50 17 be→ 对应第一个64位字段的前4字节a3 14→ 第二个16位字段4b b2→ 第三个16位字段92 c0→ 第四个16位字段51 35 b4 7f 8c 45→ 最后48位字段
这些二进制值包含大量非打印字符、不符合文本编码规则的字节(比如0xbe在UTF-8中属于无效起始字节),所以强行解码成文本必然出现乱码或报错。
2. str(uuid)是二进制UUID的格式化输出
str(my_uuid)得到的是UUID的标准字符串表示,这是一种人为定义的格式化规则:把16字节二进制数据按每4位一组转成十六进制字符,再用-分隔固定位置的字段。它和bytes的原始二进制数据不存在直接的编码/解码关系。
3. 从bytes还原UUID字符串的正确方式
如果已有bytes数据,想要得到标准UUID字符串,正确做法是用uuid.UUID类重建实例后再转成字符串:
>>> import uuid >>> my_uuid = uuid.uuid4() >>> uuid_from_bytes = uuid.UUID(bytes=my_uuid.bytes) >>> str(uuid_from_bytes) '3f5017be-a314-4bb2-92c0-5135b47f8c45' # 与原UUID字符串完全一致
内容的提问来源于stack exchange,提问作者TPPZ
相关产品推荐
相关产品推荐

