编码,真的可以说是一个大坑,为了避免这个大坑,确实需要从原理上来理解,然后解决问题的时候,一一对问题进行排查即可,实在不行,真的就是print类型出来,看到底是什么问题。
首先,在python2环境下,默认的编码格式是ASCII编码,在没有修改编码格式的时候,在.py文件中,无法正常的打印汉字,并且在读取中文的时候也会出错。这个时候报错信息为
File "D:/work_offer/6.25.py", line 2
SyntaxError: Non-ASCII character '\xe4' in file D:/work_offer/6.25.py on line 2, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details
解决策略: 在.py文件中头部加入这样一行
# -*- coding:utf-8 -*-
在python3的环境下,默认的编码格式是utf-8,可以正常的读写中文,这个时候不需要额外的指定编码方式。
所以,我们现在需要明确的几点问题,第一个问题是字符的编码方式有哪些?第二个问题是字符的编码方式之间怎么进行转换?第三个问题是如果不能解决编码问题,我们如何来进行排查问题呢?第四个问题,我们一些设置的根源解决方法是为什么可以达到目的,我们从这几个问题,逻辑不太顺的情况下,慢慢的回答这些问题。
一,字符的编码方式
想到编码方式,我就想到了百家争鸣,这是个好事,但多样性,不统一性也带来了很多的问题。很多的编码方式,因为没有统一的格式,所以还得各种转换,给程序员带来了很多的问题。我们慢慢的学习,逐个攻破这些问题。
【ASCII】很常用的编码方式,把英文字母,数字,标点符号,特殊的符号(2的7次,128个),但真的最大的问题嘛就是只考虑英文,没有考虑中文的情况。。。
【GB2312,GBK】对于中文的编码方式,解决了汉字编码的方式。
【Unicode】统一的编码方式,想要一统天下,也称为了万国码,用16位长的数字来进行表示,固定长度,解决了要表达数量巨大的字符编码的问题,但也有很大的问题,就在于对空间的利用率不高,也就是很多的浪费。仅仅是字符集。。
【UTF-8】在Unicode的基础上,实现不等长的编码,也就是可以更好的利用空间,利用率更高,更适合传输过程。
【ANSI】多字节字符系统,也就是对于ASCII编码的扩展。。。对于中文来说,典型的ANSI编码为GB2312。
在window记事本对文字进行存储是,默认的是ANSI方式,当然可以选择Unicode,UTF-8等方式,只是在开头会有几个多出来的字节,来表明编码的方式。在Unicode前加的是FFFE,在UTF-8前面加的是EF,BB,BF。在用应用软件打开文件的时候,需要先检测头部的标识,来明确编码方式。
在这,我们应该还是有疑问的,也就是从之前的ascii编码方式,然后发现不适用,然后出现各种的编码方式,比如中文中的GB2312等,这些都叫做ANSI,之后有想要一统天下的编码方式,也就是Unicode,但Unicode只是字符集,不是实现方式,而UTF-8是Unicode的一种编码实现方式。
更近一步说明,Unicode是一种字符类型的对象,与str是一个级别的。。然后表示的是类型,然后str可以是各种编码实现,也就是str存储的就是编码之后的结果,而Unicode,是表示Unicode字符集的结果。二者进行转换,用decode和encode来实现。decode是将str编码方式(如utf-8方式)编码为Unicode字符串,而encode是将unicode字符串解码成为Str类型,可以指定解码时所用的编码方式。
二,字符之间的编码方式
我们上面讲的比较常用的就是ASCII编码,UTF-8编码,GBK编码(GB2312编码),而我们说的这些编码是对于str数据类型来说的,也就是str数据中存储的就是这些编码之后的结果,而对于Unicode数据类型,存储的就是Unicode编码的情况,我们可以解码encode为str数据类型,利用上面制定的编码方式,而对于str数据类型,我们可以编码decode为unicode数据类型,但需要指明是从哪个类型转换过来。
三,我们可以做些什么来排查问题?
首先,我们对于一个数据,我们可以通过type来展示数据类型。
print type(variable)
其次,我们可以通过chardet来判断str数据类型的编码方式
import chardet
print chardet.detect(variable)
最后,还是可以通过内置函数来实现判断,也就是isinstance来进行判断。
print isinstance(s, basestring)
四,我们还是回到python的环境来进行考虑编解码的问题。
>>> import sys
>>> sys.getdefaultencoding()
‘ascii‘
>>> reload(sys)
<module ‘sys‘ (built-in)>
>>> sys.setdefaultencoding(‘utf-8‘)
>>> sys.getdefaultencoding()
‘utf-8‘
str.encode(‘other_coding‘)
设置整个系统缺省的编码方式,也就是不单单在本.py脚本中是采用这种方式编码,只要编码方式缺省的情况下,我们都默认为这种编码方式。