Python字符编码


在用python编程中,字符串有两种表示方法string和 ustring。为什么字符串要是用这两种表达方式,不是只用前一种呢?

使用type()函数查看,它们分别是str对象和unicode对象。这两个对象有什么区别吗?还有经常用到的encode()和decode()又是干什么的呢?都说python脚本使用的是两字节编码,这又是指什么呢?

要回答上面几个问题,首先得弄清楚关于编码的几个概念:
Character Set:字符集,是我们人可是识别的字符。如ASCII规定了127个是用一个字节可以表示的字符集,包括英文字母、数字、符号和一些控制字符。当然ASCII定义的字符集比较小。python中的Character Set基本包括目前世界上所有是用的字符,如中文、英文、日文字符等等。所以基本上所有的字符在Python 中进行处理。 Code Point :计算机是不能直接识别字符的(因为它只能直接识别二进制码),所以为了能让计算机处理和存储字符,需要将字符映射成一个数值(因为数值可以用二进制表达,计算机从而就可以识别了),这个数值叫作字符的code point。字符与其code point是一对一映射,Unicode很好的规定了这种映射关系。 Encode:unicode虽然规定了每个字符的Code Point,但并没有规定计算机如何存储这些Code Point。所有就有了UTF-8、GBK、UTF-16等编码格式,它们规定计算机如何来存储这个Code Point,每个编码格式它们存储方式都是不相同的。例如,“中”字的Code Point为U+2D2E(U表示Unicode,2D2E表示该Code Point值),使用GBK、Big5、UTF-8、UTF-16四种编码协议对该Code Point进行编码,获得的实际二进制表示如下:
       GBK      Big5        UTF-8     UTF-16
ÖÐ  ¤¤  中  -N
Decode:对实际的二进制进行解码,获取它所代表字符的Code Point。如“ÖД使用GBK解码,将获得2D2E(“中”的Code Point ),如果使用UTF-8对其进行解码,就会出错,因为它不是用UTF-8编码的。

上面简单介绍下字符及编码解码的概念,可参考博文《字符的编码与解码》。 Python中使用两种字符串表达方式,是为了区分字符与实际表示字符的二进制信息。unicode对象用来表示字符,它不涉及字符的底层的二进制编码信息。str对象是用来表示字符的二进制信息。一个unicode对象可以使用多种编码格式(如UTF8、GBK)编码(encode)成多个str对象,每个str对象表示该字符串的一种二进制表达。多个不同的str对象可以解码成相等的unicode对象(表示字符串相同,但内存位置不同)。 unicode的存在也是为了解决因采用不同编码格式导致的一些问题,建议大家使用unicode对象来存放字符串,统一格式。unicode虽然不规定具体的二进制信息,但为了存放每个字符的Code Point值,需要两个字节,所以说Python采用的是二进制编码(不知道这么理解可对?)。
str对象:
称字符串,它是字符串使用特定编码格式进行编码后的二进制表达,实际代表用于存储二进制信息的字节串。所以称它为“字节串”更合适。如
>>> str = '你好'   #采用系统设定的编码格式对“你好”进行编码,可通过locale命令查看。
>>> str
'你好'    #当locale设置为utf8时,'你好'的编码后的二进制表达,一个六字节的字节串
Unicode对象:
用于表达“字符”,因为计算机不用直接识别字符,所以使用Code Point来代替字符。如下:
>>> u你好
u'你好'
Code Point 4F60表示“你”,597d表示“好”。它只是一个数值与字符映射,不用于具体编码。

对一个str对象进行解码,可以获得它表达字符串的Code Point,即unicode对象。对unicode对象进行编码,可获得它的实际二进制表达,即str对象。当想把str对象从一中编码格式转换成另一种编码格式时,首先得把str转换成unicode对象,再从unicode对象转换成另外一种编码格式的str对象。下面执行一个str对象从utf8格式到gbk格式的转换:
>>> str=你好
>>> str
'你好'         # 采用OS的utf8编码格式
>>> unicode=str.decode(utf8)     # 解码成Code Point值 
>>> unicode
u'你好'
>>> str_gbk=unicode.encode(gbk)  # 将Code Point编码成GBK格式
>>> str_gbk
'ÄãºÃ'

>>> unicode.encode()               # 如果编码不指定格式,将采用系统默认的编码格式进行编码。对于decode也一样。这里由于ASCII不能对中文字符编码,所以出错了。
Traceback (most recent call last):
  File , line 1, in 
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)

>>> u = u你好     #前缀u自动把字符串从utf8转换成unicode格式了
u'你好'

写文件:
>>> file=open(test.txt, a)
>>> file.write(str)
>>> file.write(str_gbk)
>>> file.write(unicode)
Traceback (most recent call last):
  File , line 1, in 
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)
从上面看,UTF8格式的str对象和GBK格式的str对象成功的写入test.txt文件,然而在将unicode对象写入文件时,出现错误了。这是为什么呢? str对象表示字符串经编码后的二进制信息,可以直接写入文件。然后unicode对象表示的是字符串的Code Point值,是抽象的值,用来表示字符,是不能直接写入文件的。所以Python试图使用默认的编码格式ASCII,对unicode对象进行编码,然后将结果存入文件。但是由于ASCII不能对”你好”进行编码,所以报错了。
 

 

 						

评论关闭