为何Python3中decode('utf-16')失败(Python2中可正常运行)?
问题解析与解决方案
为什么两个Python版本表现不同?
核心原因是Python2和Python3的字符串模型完全不同,咱们一步步拆解来理解:
在Python2中的逻辑
Python2里的chr(145)返回的是字节串(str类型),对应字节值\x91;chr(78)是字符N,对应字节\x4e。两者拼接后得到\x91\x4e(刚好2个字节),调用.decode('utf-16')时,UTF-16编码要求每2个字节对应一个Unicode字符,这里的字节序列会被自动识别为UTF-16LE,解码后得到u'\u4e91'(也就是汉字“云”),完全符合编码规则。
而chr(93)在Python2中是],对应字节\x5d,拼接\x4e后是\x5d\x4e(同样2个字节),自然能正常解码为u'\u4e5d'(汉字“稽”)。
在Python3中的问题
Python3彻底重构了字符串模型:
chr(n)返回的是Unicode字符串(str类型),对应U+00XX的编码点(比如chr(145)是U+0091,一个不可见的控制字符)。- 当你调用
.encode('utf-8')时,U+0091的UTF-8编码是2个字节\xc2\x91,而chr(78)(U+004E)的UTF-8编码是1个字节\x4e。拼接后的字节串是b'\xc2\x91\x4e'——总共3个字节,而UTF-16要求必须是偶数个字节,直接就触发了UnicodeDecodeError: truncated data(数据截断)的错误。
那为什么chr(93)+chr(78)在Python3中能正常运行?因为U+005D(])的UTF-8编码就是单字节\x5d,拼接后字节串是b'\x5d\x4e'(2个字节),刚好满足UTF-16的要求,所以能正确解码。
如何在Python3中正确实现?
我们的目标是构造出Python2中那串原始字节\x91\x4e,再解码为UTF-16。有两种简单的方式:
方式1:直接构造字节串字面量
直接写出目标字节序列,再解码:
b'\x91\x4e'.decode('utf-16') # 输出:'云'(即 '\u4e91')
方式2:模拟Python2的chr行为
Python2的chr(n)(n<256)等价于Python3的bytes([n])(生成单字节的字节串),所以可以这样写:
(bytes([145]) + bytes([78])).decode('utf-16') # 输出同样是 '云'
两种方式都能得到你想要的'\u4e91'结果,本质都是先构造正确的UTF-16字节序列,再进行解码,避开Python3中chr返回Unicode字符串的特性。
内容的提问来源于stack exchange,提问作者pingze
相关产品推荐
相关产品推荐

