Python中的编码问题

前言

在使用Python2.X处理字符串,特别是中文的过程中,编码一直是个令人头疼的问题。本人也遇到过很多次,通常Google一下,解决了就忘了,没有深入研究过。这次又遇到,认真学习了下原理,在此记录一下。

字符串的存储

我们先来看下面这个字符串:

1
s = "你好"

s是个字符串,它本身存储的就是字节码。那么这个字节码是什么格式的?
如果这段代码是在解释器上输入的,那么这个s的格式就是解释器的编码格式,对于windows的cmd而言,就是gbk。
如果这段代码是保存后才执行的,比如存储为utf-8(文件头指定了# -- coding: utf-8 --),那么在解释器载入这段程序的时候,就会将s初始化为utf-8编码。

unicode

unicode是一种编码标准,具体的实现标准可能是utf-8,utf-16,gbk ……
python 在内部使用两个字节来存储一个unicode,使用unicode对象而不是str的好处,就是unicode方便于跨平台。
你可以用如下两种方式定义一个unicode:

1
2
s = u"你好"
s = unicode("你好", "utf-8")

encode与decode

encode与decode是Python中常用的编解码方法,通常我们会这样写:

1
2
3
4
5
6
7
8
# -*- coding:utf-8 -*-
s = "你好"
# : s是一个utf-8格式的字节串
u = s.decode("utf-8")
# : s被解码为unicode对象,赋给u
sg = u.encode("gbk")
# : u被编码为gbk格式的字节串,赋给sg
print sg

但实际上,这一段代码在执行时很可能会遇到这样的问题:

1
2
UnicodeDecodeError: 'ascii' codec can't decode byte 0x9f in position 3:
ordinal not in range(128)

这是为什么呢?因为Python对str进行编码时,会先用默认编码将自己解码为unicode,然后在将unicode编码为你指定编码。
这就引出了python2.x中在处理中文时,大多数出现错误的原因所在:python的默认编码,defaultencoding是ascii,可以通过sys.getdefaultencoding()来查看
也就是说,我们在调用encode方法时,它实际上进行的操作是:

1
s.decode('ascii').encode('gbk')

设置defaultencoding

知道了问题的原因所在,解决就比较简单了,设置默认编码

1
2
3
import sys
reload(sys)
sys.setdefaultencoding('utf-8')

文件头声明编码的作用

顶部的:# -- coding: utf-8 --目前看来有三个作用。

  1. 如果代码中有中文注释,就需要此声明
  2. 比较高级的编辑器(比如emacs),会根据头部声明,将此作为代码文件的格式。
  3. 程序会通过头部声明,解码初始化 u”人生苦短”,这样的unicode对象,(所以头部声明和代码的存储格式要一致)
欢迎打赏!