2.5.3 Python的编码问题
下面来了解一下在Python中常见的编码方式。
·GB2312:中国规定的汉字编码,也可以说是简体中文的字符集编码。
·GBK:GB2312的扩展,除了兼容GB2312外,它还能显示繁体中文,还有日文的假名。
·CP936:CP936其实就是GBK,IBM在发明Code Page时将GBK放在了第936页,所以也称为CP936。
·Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。UTF-8、UTF-16、UTF-32都是将数字转换到程序数据的编码方案。UTF-8(8-bit Unicode Transformation Format)是最流行的一种对Unicode进行传播和存储的编码方式。它用不同的Byte来表示每一个代码点。每个ASCII字符只需要用一个Byte,与ASCII的编码是一样的。所以说ASCII是UTF-8的一个子集。
在开发Python程序的过程中,会涉及三个方面的编码:
·Python程序文件的编码。
·Python程序运行时环境的编码。
·Python程序读取外部文件、网页的编码。
下面用程序来看一下不同的编程情况。
1)Python程序文件的编辑,这里还是沿用前面的环境,先用PyCharm写一段测试代码,内容如下:
print 'hello,余江洪!'
然后执行,报错如下:
File "test1.py", line 1 SyntaxError: Non-ASCII character '\xe4' in file test1.py on line 1, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details
这是因为PyCharm编辑器默认的编码是ASCII,它是无法识别中文的,所以会弹出这样的提示。这也是我们在大多数情况下写Python程序时习惯在第一行加上以下语句的原因:
#-*- encoding:utf-8 -*-
声明文件编码即可解决问题。
2)Python程序运行时系统环境或IDE的编辑。假设这里有IPython,输入如下命令:
In [1]: import sys In [2]: sys.getdefaultencoding()
显示结果如下:
Out[2]: 'ascii'
那么我们应该如何修改成UTF-8编码呢?需要在程序前面加上如下三行:
import sys reload(sys) sys.setdefaultencoding('utf-8')
对应C/C++的char和wchar_t,Python中也有两种字符串类型,即str与unicode。那么,我们应该如何来区分它们呢?
其实这和密码领域类似,从明文到密码是加密,从密码到明文是解密。在Python语言的设计中,编码为Unicode→str,解码则为str→Unicode。编码和解码也会涉及编码/解码方案(对应加密/解密算法),Unicode相当于明文,其他编码则相当于密码。在Python中,编码函数是encode(),解码函数是decode()。所以,从Unicode转str是encode(),而反过来叫decode()。
下面写一个小程序来验证:
#-*- encoding:utf-8 -*- import sys import string #设置sys.getdefaultencoding()的值为'utf-8' reload(sys) #reload才能调用setdefaultencoding方法 sys.setdefaultencoding('utf-8') #设置'utf-8' #这个是str的字符串 s = '新年快乐' #这个是Unicode的字符串 u = u'新年快乐' print isinstance(s, str) #True print isinstance(u, unicode) #True #从str转换成Unicode print s.decode('utf-8') #从Unicode转换成str print u.encode('utf-8')
输出结果如下:
True True 新年快乐 新年快乐
在工作中常会存在中文输入报错的问题,这里可以写一个函数来验证输入的Unicode是否是中文,程序内容如下:
#!/usr/bin/env python -*- coding:utf-8-*- import sys reload(sys) sys.setdefaultencoding('utf-8') # 判断一个Unicode是否是中文 def is_chinese(uchar): if u'\u4e00' <= uchar<=u'\u9fff': print 'yes' return True else: print 'no' return False is_chinese('余洪春')
3)对于外部文件或网页,我们可以利用chardet模块来正确识别它们到底采取的是哪种编码。chardet是一个非常优秀的编码识别模块。另外,它是Python的第三方库,需要下载和安装,这里直接用pip命令来安装:
pip install chardet
以笔者的技术博客来举例说明如何利用chardet得知网页编码方式,代码如下:
#!/usr/bin/env python import chardet import urllib myweb = urllib.urlopen('http://yuhongchun.blog.51cto.com').read() char = chardet.detect(myweb) print char
代码运行结果如下:
{'confidence': 0.99, 'language': '', 'encoding': 'utf-8'}
结果表示有99%的概率认为这段代码是UTF-8编码方式。