Linux集群之美
上QQ阅读APP看书,第一时间看更新

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编码方式。