导航: 起始页 > Dive Into Python > XML 处理 > Unicode | << >> | ||||
Python 研究(Dive Into Python)Python 从新手到高手 [DIP_5_4_CPUG_RELEASE] |
Unicode 是一个系统,用来表示世界上所有不同语言的字符。当 Python 解析一个 XML 文档时,所有的数据都是以unicode的形式保存在内存中的。
一会儿你就会了解,但首先,先看一些背景知识。
历史注解. 在unicode之前,对于每一种语言都存在独立的字符编码系统,每个系统都使用相同的数字(0-255)来表示这种语言的字符。一些语言(象俄语)对于如何表示相同的字符还有几种有冲突的标准;另一些语言(象日语)拥有太多的字符,需要多个字符集。在系统之间进行文档交流是困难的,因为对于一台计算机来说,没有方法可以识别出文档的作者使用了哪种编码模式;计算机看到的只是数字,并且这些数字可以表示不同的东西。接着考虑到试图将这些文档存放到同一个地方(比如在同一个数据库表中);你需要在每段文本的旁边保存字符的编码,并且确保在传递文本的同时将编码也进行传递。接着考虑多语言文档,即在同一文档中使用了不同语言的字符。(比较有代表性的是使用转义符来进行模式切换;扑,我们处于俄语 koi8-r 模式,所以字符 241 表示这个;扑,现在我们处于 Mac 希腊语模式,所以字符 241 表示其它什么。等等。)这些就是unicode被设计出来要解决的问题。
为了解决这些问题,unicode用一个 2 字节数字表示每个字符,从 0 到 65535。[5] 每个 2 字节数字表示至少在一种世界语言中使用的一个唯一字符。(在多种语言中都使用的字符具有相同的数字码。)这样就确保每个字符一个数字,并且每个数字一个字符。Unicode数据永远不会模棱两可。
当然,仍然还存在着所有那些遗留的编码系统的情况。例如,7位 ASCII,它可以将英文字符存诸为从0到127的数值。(65是大写字母“A”,97是小写字母“a”,等等。)英语有着非常简单的字母表,所以它可以完全用7位 ASCII 来表示。象法语、西班牙语和德语之类的西欧语言都使用叫做ISO-8859-1的编码系统(也叫做“latin-1”),它使用7位 ASCII 字符表示从0到127的数字,但接着扩展到了128-255的范围来表示象n上带有一个波浪线(241),和u上带有两个点(252)的字符。Unicode使用同7位 ASCII 码一样的字符表示0到127,同ISO-8859-1一样的字符表示128到255,接着使用剩余的数字,256到65535,扩展到表示其它语言的字符。
在处理unicode数据时,在某些地方你可能需要将数据转换回这些遗留编码系统之一。例如,为了同其它一些计算机系统集成,这些系统期望它的数据使用一种特定的单字节编码模式,或将数据打印输出到一个非unicode识别终端或打印机。或将数据保存到一个明确指定编码模式的 XML 文档中。
在了解这个注解之后,让我们回到 Python上来。
从2.0版本开始,Python 在整个语言的基础上已经支持unicode。XML 包使用unicode来保存所有解析了的 XML 数据,而且你可以在任何地方使用unicode。
例 9.13. unicode介绍
>>> s = u'Dive in' >>> s u'Dive in' >>> print s Dive in
例 9.14. 存储非 ASCII 字符
>>> s = u'La Pe\xf1a' >>> print s Traceback (innermost last): File "<interactive input>", line 1, in ? UnicodeError: ASCII encoding error: ordinal not in range(128) >>> print s.encode('latin-1') La Peña
还记得我说过:一旦需要从一个unicode得到一个正常字符串,Python通常默认将unicode转换成 ASCII 吗?嗯,这个默认编码模式是一个可以定制的选项。
例 9.15. sitecustomize.py
# sitecustomize.py # this file can be anywhere in your Python path, # but it usually goes in ${pythondir}/lib/site-packages/ import sys sys.setdefaultencoding('iso-8859-1')
例 9.16. 设置默认编码的效果
>>> import sys >>> sys.getdefaultencoding() 'iso-8859-1' >>> s = u'La Pe\xf1a' >>> print s La Peña
例 9.17. 指定.py文件的编码
如果你打算在你的 Python 代码中保存非 ASCII 字符串,你需要在每个文件的顶端加入编码声明来指定每个.py文件的编码。这个声明定义了.py文件的编码为UTF-8:
#!/usr/bin/env python # -*- coding: UTF-8 -*-
现在,想想 XML 中的编码应该是怎样的呢?不错的是,每一个 XML 文档都有指定的编码。重复一下,ISO-8859-1是西欧语言存放数据的流行编码方式。KOI8-R是俄语流行的编码方式。编码,如果指定了的话,都在 XML 文档的首部。
例 9.18. russiansample.xml
<?xml version="1.0" encoding="koi8-r"?> <preface> <title>Предисловие</title> </preface>
例 9.19. 解析russiansample.xml
>>> from xml.dom import minidom >>> xmldoc = minidom.parse('russiansample.xml') >>> title = xmldoc.getElementsByTagName('title')[0].firstChild.data >>> title u'\u041f\u0440\u0435\u0434\u0438\u0441\u043b\u043e\u0432\u0438\u0435' >>> print title Traceback (innermost last): File "<interactive input>", line 1, in ? UnicodeError: ASCII encoding error: ordinal not in range(128) >>> convertedtitle = title.encode('koi8-r') >>> convertedtitle '\xf0\xd2\xc5\xc4\xc9\xd3\xcc\xcf\xd7\xc9\xc5' >>> print convertedtitle Предисловие
总结一下,如果你以前从没有看到过unicode,倒是有些唬人,但是在 Python 处理unicode数据真是非常容易。如果你的 XML 文档都是7位的 ASCII(像本章中的例子),你差不多永远都不用考虑unicode。Python 在进行解析时会将 XML 文档中的 ASCII 数据转换为unicode,在任何需要的时候强制转换回为 ASCII,你甚至永远都不用注意。但是如果你要处理其它语言的数据,Python 已经准备好了。
进一步阅读
- Unicode.org是unicode标准的主页,包含了一个简要的技术简介。
- Unicode教程有更多关于如何使用 Python unicode函数的例子,包括甚至在并不真的需要时如何将unicode强制转换为 ASCII。
- PEP 263涉及了何时、如何在你的.py文件中定义字符的更多细节。
Footnotes
[5] 这一点,很不幸仍然 过分简单了。现在unicode已经扩展用来处理古老的汉字、韩文和日文文本,它们有太多不同的字符,以至于2字节的unicode系统不能全部表示。但当前 Python 不支持超出范围的编码,并且我不知道是否有正在计划进行解决的项目。对不起,你已经到了我经验的极限了。
<< XML 解析 |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | |
搜索元素 >> |