Py2的编码问题真是历史悠久,下边这个报错更是经常见到。
在避开Py2的编码坑之前,我们需要了解一下一些常见的编码。
常见编码
ASCII
ASCII(American Standard Code for Information Interchange,美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。它是现今最通用的单字节编码系统。
Unicode
Unicode(统一码、万国码、单一码)是计算机科学领域里的一项业界标准,包括字符集、编码方案等。Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。
UTF-8
UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码,又称万国码。由Ken Thompson于1992年创建。现在已经标准化为RFC 3629。UTF-8用1到4个字节编码Unicode字符。用在网页上可以统一页面显示中文简体繁体及其它语言(如英文,日文,韩文)。
GB2312
GB2312编码由中国国家标准总局1980年发布,1981年5月1日开始实施的一套国家标准,适用于汉字处理、汉字通信等系统之间的信息交换,通行于中国大陆;新加坡等地也采用此编码。中国大陆几乎所有的中文系统和国际化的软件都支持GB2312。基本集共收入汉字6763个和非汉字图形字符682个。
GBK
GB2312的出现,基本满足了汉字的计算机处理需要,它所收录的汉字已经覆盖中国大陆99.75%的使用频率,不过 GB2312 还是不能100%满足中国汉字的需求,对一些罕见的字和繁体字 GB2312 没法处理,后来就在GB2312的基础上创建了一种叫GBK 的编码,GBK不仅收录了27484个汉字,同时还收录了藏文、蒙文、维吾尔文等主要的少数民族文字。
编码问题
背景介绍完毕。回到Python2当中,Python2默认编码是ASCII。
|
|
如果.py文件中包含中文字符(严格的说是含有非anscii字符),则需要在第一行或第二行指定编码声明:
否认将会看到这样的报错
|
|
在Python2中有两种字符串类型,分别是str和unicode,他们都是basestring的派生类。
对unicode进行指定格式的编码后,就是str。
对str进行指定格式的解码后,就是unicode。
举个例子:
|
|
也就是说,utf-8,gb2312,gbk编码的字符串,都可以通过decode函数,转换为unicode,而unicode字符串,可以通过encode函数指定编码,转换为utf-8,gb2312,gbk等任意编码的字符串。
unicode就是一个编码转换的中间人。
避开编码坑,最重要的就是清楚源字符串的编码和输出环境的编码。最好是在Python处理过程中,都先转换为unicode,在最后输出的时候,再进行编码。
举个乱码的例子。
|
|
在IDE里边,一切正常,可是当你在Windows的CMD下运行的时候,乱码鸟
|
|
这是为什么呢?CMD的默认输出编码是GB2312,而我们提供的是UTF-8编码的字符串,于是解析的时候,出现了乱码。
解决方案一:
修改CMD的默认编码为UTF-8,在CMD里边输入 CHCP 65001即可。
解决方案二:
在Py文件里边,将字符串的编码转换成Unicode,这样可以有几种写法。
|
|
|
|
|
|
最推荐的方式是第三种,通过__future__模块引入Py3的一个新特性,字符串默认使用unicode编码。
而在文章最开始列出来的报错,有两种常见情况。
一是unicode和str混用,进行了运算
二是对字符串进行编码解码的时候,指定了错了编码类型。
结论
在Python2中,进行编码转化时候,需要先转为unicode编码,再进行下一步的转化。如:utf-8—>unicode—>gb2312
推荐实践
从__future__模块引入unicode_literals
使用chardet检测编码格式,chardet是一个检测字符串编码的第三方库,必备神器,通过 pip install chardet 安装。
|
|
- 使用codecs打开文件
上文提到,推荐在Py内处理文本之前,都先转为unicode编码,自带的open函数,并不具备这个功能,推荐使用codecs模块的open函数来打开文件,同时指定文件编码,将读取的文本转化为unicode编码。
|
|
说点别的
经常会看到有人问这样一个问题:打印字典和列表的时候,怎么显示成中文?
|
|
解决方法是:
|
|