Python食谱-1.22.将Unicode字符打印到标准输出

原文作者:David Ascher
中文翻译:Tony (digitalsatori)

问题

需要将Unicode字符打印到标准输出(比如在Debug时),但是它们不能使用默认的编码,怎么办?

解决方法

使用Python标准库中的 codecs 模块作为编码转换器来封装 sys.stdout (标准输出流)。比如我们的输出是到一个使用ISO-8859-1编码的终端,可以这样来写代码:

import codecs, sys
sys.stdout = codecs.lookup('iso8859-1')[-1](sys.stdout)

讨论

Unicode字符串处在一个足以容纳全世界所有语言所包含的字符的空间中。幸运的是,作为Unicode的使用者,我们不必了解Unicode字符串的内部表现方式。但是对于象 sys.stdout 这样的文件流,只能处理与特定编码关联的字节。我们可以改变Python的 site 模块来改变文件所使用的默认编码,但是这样的改变会全局影响Python ,使其它使用Python安装时的默认编码的程序出现混乱。(Python的默认标准编码是ASCII)。因此,我们不推荐这类改动。

本配方采用了一个更好的方法:将 sys.stdout 重新绑定到一个接收Unicode输入,以ISO-8859-1(也称为"Latin-1")编码输出的文件流。该方法并不会改变之前的 sys.stdout 的编码。首先我们保存当前的以ASCII为编码的 sys.stdout:

>>> old = sys.stdout

然后,我们创建一个无法通过 sys.stdout 直接输出的Unicode字符串:

>>> char = u"\N{LATIN SMALL LETTER A WITH DIAERESIS}"
>>> print char
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
UnicodeError: ASCII encoding error: ordinal not in range(128)

如果在做以上操作时没有出现错误,那是因为Python认为它知道你的终端所使用的编码(比如你的终端是Python自带的开发环境IDLE, 多数情况下Python会使用正确的编码)。但是如果确实有错误信息出现,或者没有出现错误信息,但是输出并不是期待中的输出,因为Python并不知道你的终端使用的是比如UTF-8这种编码。我们可以将 sys.stdout 用以UTF-8编码的 codecs 输出流封装,并将 sys.stdout 重新绑定到这个封装的输出流:

>>> sys.stdout = codecs.lookup('utf-8')[-1](sys.stdout)
>>> print char
ä

以上方法工作的前提是,运行Python互动解释器的终端,终端模拟器,或其它窗口支持UTF-8编码,并且拥有需要显示的字符的字体。如果你没有符合这样要求的程序或设备,请在互联网上下载适用于你所使用平台的程序。

参见

在Python库参考手册和Python in a Nutshell中关于 codecssite 模块,以及 sys 模块中的 setdefaultencoding 函数; Python食谱1.20 Python食谱1.21

One Response to “Python食谱-1.22.将Unicode字符打印到标准输出”

  1. [...] uni­code类型 ,以及unidata模块和codecs的内容。另外,请参考 Python食谱1.21 和 Python食谱1.22 的内容。 网络书签 [...]

Leave a Response