Python编码问题一直困扰了我许久,之前有过一些总结,但并不系统,比较凌乱。当然python2.x编码问题本身,便是剪不断理还乱。本篇将系统介绍python2.x编程中会遇到的一些编码问题,并给出解决方案。基于对编码问题的摸索了解,我也尝试写了一个编码转换模块Transcode ,应该能解决绝大部分新手的疑难杂症。当然,python大神可以绕道而行,至于使用3.x的朋友,以后将会成文介绍。
python编程中会经常遇到操作系统编码、文件编码、控制台输入输出编码、网页编码、源代码编码、python编码,本文将会逐一介绍。首先我们来看看一些常见的编码情况:
|
|
将以上这段代码在windows与linux系统下分别运行,查看输出结果。
windows终端结果:
|
|
Linux终端结果:
|
|
操作系统编码
操作系统默认编码可以通过sys.getdefaultencoding()函数获取,可以看到windows与linux下默认都为ascii编码,而我们知道ascii编码不支持中文。那么操作系统编码将在python程序的何处会被用到呢?何时又会引发血案?
触发异常点
经过测试,我发现当需要将unicode格式的字符串存入到文件时,python内部会默认将其先转换为Str格式的系统编码,然后再执行存入步骤。而在这过程中,容易引发ascii异常。
实例证明:
|
|
报错异常信息:UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position 0-1……
说明:因为ascii不支持中文,而变量a为unicode格式的中文字符串,因此无法进行编码而引发异常。
解决方案
设置系统编码为utf-8或者gbk。
|
|
说明:在windows下将其设置为gbk,在linux在设置为utf-8.
终端编码
windows下终端指的是控制台,在控制台上输入输出有着其本身的编码格式,如windows控制台输入输出编码都为cp936。原谅我是第一次看到此编码,于是上网查了会,发现其实它就是常见的GBK编码;而linux终端的输入输出编码都为utf-8。如果我们编写的程序,不会再终端输入输出任何内容,则可以忽略此编码,如若不然终端编码将会非常重要。
乱码点
我们在终端执行python脚本时,经常会遇到输出中文乱码,而这往往是因为输出的字符串本身编码与控制台编码不一致。
实例证明:
|
|
windows控制台输出结果:
|
|
linux终端输出结果:
|
|
造成这种差异的原因在于windows控制台为gbk编码,而变量a本身为utf-8编码。
解决方案
|
|
将变量a从utf-8编码转换为gbk编码。
python编码
python2.x从外部获取的内容都是string编码,其内部分为String编码与Unicode编码,而String编码又分为UTF-8,GBK,GB2312等等。因此为了避免不同编码造成的报错,python内部最好都转化为unicode编码,在输出时再转化为str编码 。可以用encode()/decode()函数,将string与unicode编码互换。
触发异常点
基本在于python内部变量编码与控制台编码,或者其他编码相结合时触发。
实例证明:
|
|
运行结果:
|
|
说明:windows下控制台输入输出都是gbk编码格式,而代码中定义的变量a为str,utf-8格式,所以会出现乱码。如果想创建一个unicode编码字符串的变量,则可以a=u”123”,在双引号前面加上一个u,表示a为unicode编码。
解决方案
|
|
说明:首先我们定义的变量a是str格式,编码为utf-8的字符串,我们要将之转化为str格式,GBK编码的字符串。在python内部无法直接转化,需要借助decode()与encode()函数。decode()函数先将str格式的字符串a转化为unicode,再将unicode编码为str格式GBK。而在Unix系统下,不存在这个问题,因为都是utf-8编码,不会存在乱码。print语句默认会将unicode编码的字符串,encode为相应系统的str编码并输出(windows下为gbk,unix下为utf-8),因此不用担心print unicode编码字符串会报错。
源代码编码
源代码编码指的是python程序本身的编码,默认为ascii。
触发异常点
python程序本身要被解释器解析执行,需要先被转化为二进制代码。而在这过程中容易引发异常,原因同样是ascii不支持中文,因此当python程序中出现中文时,哪怕是注释,也会引发ascii异常。
实例证明:
|
|
报错:SyntaxError: Non-ASCII character ‘\xe7’……
解决方案
|
|
python程序开头加上这句代码,指定python源代码编码格式为utf-8。
文件编码
文件编码指的是,python程序从文件中获取的内容的编码格式。可以用sys.getfilesystemencoding()函数获取,windows下为mbcs,linux下为utf-8。至于mbcs,是一种多字节编码(没搞很明白)。
触发异常点(读取文件内容)
当python程序从文件中获取内容,并输出时,容易触发异常。
实例证明:
|
|
运行结果:
|
|
可以看到windows下,从文件中读取的编码格式为Str,GBK格式(因为控制台输出没有中文乱码);而在Unix下为Str,Utf-8格式。从输出内容来说,并没有触发异常,然而当这些内容与python程序自身内容相结合时,容易触发异常。
解决方案
在windows下,最好将文件内容转为unicode,可以使用codecs:
|
|
将格式为gbk的文件内容转化为unicode格式,当然也可以直接使用open(“”,”r”).read().decode(“gbk”)
触发异常点(写入文件内容)
参考操作系统编码触发异常点,即将中文unicode字符写入文件时,容易触发异常。
解决方案
参考操作系统编码解决方案,或者手动将unicode编码转换为str编码。
实例证明:
|
|
当然如果变量a本身就是Str则不会报错,只是utf-8编码的内容写入windows文件中,显示会乱码。
网页编码
网页编码,通常在写爬虫的时候经常遇到,再结合系统编码,python编码,文件编码,往往会搞得一团乱。在程序中我们应该分别处理这些编码,在python内部全部转化为unicode。那么网页编码又有哪些格式呢?
常见格式:utf-8,gbk,gb2312
触发异常点
还是在于从网页中获取的源码编码与终端编码,甚至python内部编码不一致的情况。
实例证明:
|
|
运行结果:
|
|
说明:这个网站的编码是utf-8,而且python从网页上爬取的内容都为Str格式,在windows控制台下输出会乱码。
解决方案
依照之前做法,先将其转化为unicode。而相应的正则也可以为unicode编码,如:res=r’’+u”新成员”。可以通过chardet模块判断网页编码类型,返回的是一个带概率的字典。
编码判断
判断字符串编码
|
|
返回True或者False
判断网页编码
|
|
判断编码格式,会有百分比,一般用来判断网页编码比较好。
判断系统编码
|
|
python2.x编码建议
- 请尽量在Linux系统上编程,综上我们可以知道linux下较windows,编码问题良好很多。
- python代码内部请全部使用unicode编码,在获取外部内容时,先decode为unicode,向外输出时再encode为Str
- 在定义变量或者正则时,也定义unicode字符,如a=u”中文”;res=r””+u”正则”。
其他疑难杂症
实例一:
|
|
变量a的内容本身为unicode编码,怎么正常显示输入?
解决方案:
|
|
本文转自:Python2编码之殇续集