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

Python044

怎么在Python里使用UTF-8编码,第1张

概述

在python代码即.py文件的头部声明即可

解析

py文件中的编码

Python 默认脚本文件都是 ANSCII 编码的,当文件 中有非 ANSCII 编码范围内的字符的时候就要使用"编码指示"来修正一个 module 的定义中,如果.py文件中包含中文字符(严格的说是含有非anscii字符),则需要在第一行或第二行指定编码声明:

# -*- coding=utf-8 -*-

#coding=utf-8

# 以上两种选其一即可

其他的编码如:gbk、gb2312也可以;否则会出现:

SyntaxError: Non-ASCII character '\xe4' in file test.py on line 3, but no encoding declaredsee http://www.python.org/peps/pep-0263.html for details

python中的编码与解码

先说一下python中的字符串类型,在python中有两种字符串类型,分别是 str 和 unicode,他们都是basestring的派生类;

str类型是一个包含Characters represent (at least) 8-bit bytes的序列;

unicode 的每个 unit 是一个 unicode obj

在str的文档中有这样的一句话:

The string data type is also used to represent arrays of bytes, e.g., to hold data read from a file.

也就是说在读取一个文件的内容,或者从网络上读取到内容时,保持的对象为str类型;如果想把一个str转换成特定编码类型,需要把str转为Unicode,然后从unicode转为特定的编码类型如:utf-8、gb2312等。

拓展内容

utf-8编码

UTF-8(8-bit Unicode Transformation Format)是一种针对Unicode的可变长度字符编码,也是一种前缀码。它可以用来表示Unicode标准中的任何字符,且其编码中的第一个字节仍与ASCII兼容,这使得原来处理ASCII字符的软件无须或只须做少部分修改,即可继续使用。因此,它逐渐成为电子邮件、网页及其他存储或发送文字的应用中,优先采用的编码。

UTF-8使用一至六个字节为每个字符编码(尽管如此,2003年11月UTF-8被RFC 3629重新规范,只能使用原来Unicode定义的区域,U+0000到U+10FFFF,也就是说最多四个字节):

1、128个US-ASCII字符只需一个字节编码(Unicode范围由U+0000至U+007F)。

2、带有附加符号的拉丁文、希腊文、西里尔字母、亚美尼亚语、希伯来文、阿拉伯文、叙利亚文及它拿字母则需要两个字节编码(Unicode范围由U+0080至U+07FF)。

3、其他基本多文种平面(BMP)中的字符(这包含了大部分常用字,如大部分的汉字)使用三个字节编码(Unicode范围由U+0800至U+FFFF)。

4、其他极少使用的Unicode 辅助平面的字符使用四至六字节编码(Unicode范围由U+10000至U+1FFFFF使用四字节,Unicode范围由U+200000至U+3FFFFFF使用五字节,Unicode范围由U+4000000至U+7FFFFFFF使用六字节)。

对上述提及的第四种字符而言,UTF-8使用四至六个字节来编码似乎太耗费资源了。但UTF-8对所有常用的字符都可以用三个字节表示,而且它的另一种选择,UTF-16编码,对前述的第四种字符同样需要四个字节来编码,所以要决定UTF-8或UTF-16哪种编码比较有效率,还要视所使用的字符的分布范围而定。不过,如果使用一些传统的压缩系统,比如DEFLATE,则这些不同编码系统间的的差异就变得微不足道了。若顾及传统压缩算法在压缩较短文字上的效果不大,可以考虑使用Unicode标准压缩格式(SCSU)。

互联网工程工作小组(IETF)要求所有互联网协议都必须支持UTF-8编码。互联网邮件联盟(IMC)建议所有电子邮件软件都支持UTF-8编码。

一、使用中文字符

在python源码中如果使用了中文字符,运行时会有错误,解决的办法是在源码的开头部分加入字符编码的声明,下面是一个例子:

#!/usr/bin/env python

# -*- coding: cp936 -*-

Python Tutorial中指出,python的源文件可以编码ASCII以外的字符集,最好的做法是在#!行后面用一个特殊的注释行来定义字符集:

# -*- coding: encoding -*-

根据这个声明,Python会尝试将文件中的字符编码转为encoding编码,并且,它尽可能的将指定地编码直接写成Unicode文本。

注意,coding:encoding只是告诉Python文件使用了encoding格式的编码,但是编辑器可能会以自己的方式存储.py文件,因此最后文件保存的时候还需要编码中选指定的ecoding才行。

二、中文字符的存储

>>>str = u"中文"

>>>str

u'\xd6\xd0\xce\xc4'

>>>str = "中文"

>>>str

'\xd6\xd0\xce\xc4'

u"中文"只是声明unicode,实际的编码并没有变。这样子就发生变化了:

>>>str = "中文"

>>>str

'\xd6\xd0\xce\xc4'

>>>str = str.decode("gb2312")

>>>str

u'\u4e2d\u6587'

更进一步:

>>>s = '中文'

>>>s.decode('gb2312')

u'\u4e2d\u6587'

>>>len(s)

4

>>>len(s.decode('gb2312'))

2

>>>s = u'中文'

>>>len(s)

4

>>>s = '中文test'

>>>len(s)

8

>>>len(s.decode('gb2312'))

6

>>>s = '中文test,'

>>>len(s)

10

>>>len(s.decode('gb2312'))

7

可以看出,对于实际Non-ASCII编码存储的字符串,python可以正确的识别出其中的中文字符以及中文上下文中的标点符号。

前缀“u”表示“后面这个字符串“是一个Unicode字符串”,这仅仅是一个声明,并不表示这个字符串就真的是Unicode了;就好比某正太声称自己已满18岁,但实际上他的真实年龄并不确定,现在体育界年龄造假可不稀罕幺!

那么声明成u有什么作用呢?对于Python来说,只要你声明某字符串是Unicode,它就会用Unicode的一套机制对它进行处理。比方说,做字符串操作的时候会动用到内部的Unicode处理函数,保存的时候以Unicode字符(双字节)进行保存。等等。显而易见,对于一个实际上并不是 Unicode的字符串,做Unicode动作的处理,是有可能会出问题的。 u前缀只适用于你的字符串常量真的是Unicode的情况 。

python 中的 unicode 是让人很困惑、比较难以理解的问题. 这篇文章 写的比较好, utf-8是 unicode的一种实现方式,unicode、gbk、gb2312是编码字符集.

Python 默认脚本文件都是 ANSCII 编码的,当文件 中有非 ANSCII 编码范围内的字符的时候就要使用" 编码指示 "来修正一个 module 的定义中,如果.py文件中包含中文字符(严格的说是含有非anscii字符),则需要在第一行或第二行指定编码声明: # -*- coding=utf-8 -*- 或者 #coding=utf-8

其他的编码如:gbk、gb2312也可以;否则会出现:

先说一下python中的字符串类型,在python中有两种字符串类型,分别是 str 和 unicode ,他们都是basestring的派生类;

在str的文档中有这样的一句话:

也就是说在读取一个文件的内容,或者从网络上读取到内容时,保持的对象为str类型;如果想把一个str转换成特定编码类型,需要把str转为Unicode,然后从unicode转为特定的编码类型如:utf-8、gb2312等。

unicode 转为 gb2312,utf-8等,使用 encode(encoding)

utf-8,GBK转换为 unicode 使用 unicode(s,encoding) 或者 s.decode(encoding)

普通的 str 转为 unicode,

如果直接执行s.encode('gb2312')会发生什么?

这里会发生一个异常:Python 会自动的先将 s 解码为 unicode ,然后再编码成 gb2312。因为解码是python自动进行的,我们没有指明解码方式,python 就会使用 sys.defaultencoding 指明的方式来解码。很多情况下 sys.defaultencoding 是 ANSCII,如果 s 不是这个类型就会出错。

拿上面的情况来说,我的 sys.defaultencoding 是 anscii,而 s 的编码方式和文件的编码方式一致,是 utf8 的,所以出错了:

对于这种情况,我们有两种方法来改正错误:

s = '中文'

s.decode('utf-8').encode('gb2312') ```

import sys

reload(sys) # Python2.5 初始化后会删除 sys.setdefaultencoding 这个方法,我们需要重新载入

sys.setdefaultencoding('utf-8')

str = '中文'

str.encode('gb2312')

print open("Test.txt").read()

import codecs

print open("Test.txt").read().decode("utf-8")

Traceback (most recent call last):

File "ChineseTest.py", line 3, in <module>

print open("Test.txt").read().decode("utf-8")

UnicodeEncodeError: 'gbk' codec can't encode character u'\ufeff' in position 0: illegal multibyte sequence

import codecs

data = open("Test.txt").read()

if data[:3] == codecs.BOM_UTF8:

data = data[3:]

print data.decode("utf-8")

s = "中文"

print unicode(s, "utf-8")

Traceback (most recent call last):

File "ChineseTest.py", line 3, in <module>

s = unicode(s, "utf-8")

UnicodeDecodeError: 'utf8' codec can't decode bytes in position 0-1: invalid data

s = "中文"

print unicode(s, "gbk")

s = "中文"

print unicode(s, "cp936")