怎么在Python里使用UTF-8编码?

基本概念

在Python里有两种类型的字符串类型:字节字符串和Unicode的字符串,一个字节字符串就是一个包含字节列表。 当需要的时候,Python根据电脑默认的locale设置将字节转化成字符。 在Mac OX上默认的编码是UTF-8,但是在别的系统上,大部分是ASCII。

比如创建一个字节字符串:

byteString = "hello world! (in my default locale)"

创建一个Unicode字符串:

unicodeString = u"hello Unicode world!"

将一个字节字符串转成Unicode字符串然后再转回来:

s = "hello byte string"
u = s.decode()
backToBytes = u.encode()

以上代码使用的是系统默认的字符来出来转换的。 然而,依赖系统的区域设置的字符集不是一个好主意,或许你的程序在泰文用户的电脑上就会崩溃。 最好的办法就是为字符指定一个编码:

s = "hello normal string"
u = s.decode("UTF-8" )
backToBytes = u.encode( "UTF-8" )

现在,字节字符串s就被当成一个UTF-8字节列表去创建一个Unicode字符串u, 下一行用UTF-8表示的字符串u转换成字节字符串backToBytes.

如何判断一个对象是字符串

比如这样去判断:

if isinstance( s, str ):
    pass

这样是不对的,因为Unicode字符串将不为真. 代替的是使用通用字符串类, basestring:

if isinstance( s, basestring ):# True for both Unicode and byte strings
    pass

单独判断是不是Unicode字符串:

if isinstance( s, unicode ):
    pass

读取UTF-8编码的文件

你可以手工转换从文件中读取的字符串,方法很简单:

import codecs
fileObj = codecs.open( "someFile", "r", "UTF-8" )
u = fileObj.read() # Returns a Unicode string from the UTF-8 bytes in the file

codecs模块可以处理所有的编码转换。

源码的编码声明

Python源代码默认是 ASCII.可以在源文件的第一行或者是第二行作如下声明:

# coding=UTF-8

or (using formats recognized by popular editors):

1
2
#!/usr/bin/python
# -*- coding: UTF-8 -*-

or:

1
2
#!/usr/bin/python
# vim: set fileencoding=UTF-8 :

系统编码

前面说了,Python根据电脑默认的locale设置将字节转化成字符.那如何获得系统的默认编码:

import sys
print sys.getdefaultencoding()

更改系统的默认编码:

import sys
reload(sys)
sys.setdefaultencoding('UTF-8')

为什么要reload sys模块,先看下python的模块加载过程:

# python -v
# installing zipimport hook
import zipimport # builtin
# installed zipimport hook
# /usr/local/lib/python2.6/site.pyc matches /usr/local/lib/python2.6/site.py
import site # precompiled from /usr/local/lib/python2.6/site.pyc
....

Python运行的时候首先加载了site.py,在site.py文件里有这么一段代码:

if hasattr(sys, "setdefaultencoding"):
    del sys.setdefaultencoding

在sys加载后,setdefaultencoding方法被删除了,所以我们要通过重新导入sys来设置系统编码.

参考文章