Python解决汉字编码问题:Unicode Decode Error
本文详解Python中ASCII、Unicode与UTF-8编码机制,解析读取含中文txt文件时出现的UnicodeDecodeError及编码转换错误。通过sys.setdefaultencoding、encode/decode方法及codecs库,提供解决Windows下GBK与UTF-8冲突、BOM头干扰等实际问题的方案。
前言
近期因项目需求,需读取包含中文的txt文档并进行保存。原文档采用base64编码,导致汉字读取时显示为乱码。项目组废弃base64后,先后遭遇两类编码错误:
ascii codec can't encode characters in position ordinal not in range 128 UnicodeDecodeError: ‘utf8' codec can't decode byte 0x。
若对ASCII、Unicode和UTF-8尚不熟悉,可参考往期文章《关于字符串和编码》。
理解以下三个核心概念至关重要:
- ASCII仅能表示数字、英文字母及部分特殊符号,无法表示汉字。
- Unicode和UTF-8均可表示汉字,其中Unicode为固定长度编码,UTF-8为可变长度编码。
- 内存中通常以Unicode格式存储,而磁盘文件多以UTF-8格式存储,因UTF-8能节省存储空间。
Python的默认编码是什么?
>>> import sys
>>> sys.getdefaultencoding()
'ascii'
>>> reload(sys)
<module 'sys' (built-in)>
>>> sys.setdefaultencoding('utf-8')
>>> sys.getdefaultencoding()
'utf-8'
Python默认编码为ASCII,可通过sys.setdefaultencoding('utf-8')函数修改Python的默认编码设置。
在Python中,可通过encode和decode方法改变数据编码,例如:
>>> u'汉字'
u'\u6c49\u5b57'
>>> u'汉字'.encode('utf-8')
'\xe6\xb1\x89\xe5\xad\x97'
>>> u'汉字'.encode('utf-8').decode('utf-8')
u'\u6c49\u5b57'
利用这两个函数即可设置所需编码。
那么,Python中的str类型究竟是什么?
>>> import binascii
>>> '汉字'
'\xba\xba\xd7\xd6'
>>> type('汉字')
<type 'str'>
>>> print binascii.b2a_hex('汉字')
babad7d6
>>> print binascii.b2a_hex(u'汉字')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode characters in
position 0-1: ordinal not in range(128)
>>> print binascii.b2a_hex(u'汉字'.encode('utf-8'))
e6b189e5ad97
>>> print binascii.b2a_hex(u'汉字'.encode('gbk'))
babad7d6
binascii模块用于将二进制数据转换为ASCII字符串。上述解释表明:'汉字'的类型为str,其二进制表示为babad7d6;而u'汉字'(Unicode字符串)无法直接转换为ASCII,从而引发首个错误。解决方法是将其.encode('utf-8')转换为str类型。由于命令行默认使用Windows的GBK编码,u'汉字'.encode(‘gbk')时的输出结果与'汉字'一致。
总结而言,Python中的str实质上是Unicode的一种表现形式。Python默认编码为ASCII,在尝试将非ASCII字符转换为ASCII时会报错。请牢记以下转换规则:
- unicode => encode('合适的编码') => str
- str => decode('合适的编码') => unicode
另一种简便方式是在文件头部设置编码声明,可避免诸多麻烦:
import sys
reloads(sys)
sys.setdefaultencoding('utf-8')
第二个问题出现在文件读取环节。UTF-8文件分为带BOM和无BOM两种形式,差异在于带BOM文件多出一个头部标识,导致以UTF-8方式读取时报错。我曾尝试在读取前判断并跳过BOM头,但未能成功。
最终通过查阅资料找到解决方案:使用codecs库读取文件(推测该库内置了BOM检测机制)。
import codecs codecs.open(file_name, "r",encoding='utf-8', errors='ignore')
处理编码问题时,务必深入理解ASCII、Unicode和UTF-8的工作原理。
总结
以上为本文全部内容,希望能为读者在学习或工作中提供帮助。如有疑问,欢迎留言交流。
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













