Python中print和sys.stdout.write在处理Unicode方面的差异

9
我先说一下,我已经看过这篇文章:Strange python print behavior with unicode,但是那里提供的解决方案(使用PYTHONIOENCODING)对我没用。

这是我的问题:

Python 2.6.5 (r265:79063, Apr  9 2010, 11:16:46)
[GCC 4.1.2 20080704 (Red Hat 4.1.2-44)] on linux2
>>> a = u'\xa6'
>>> print a 
¦

此功能运行良好,但是:

>>> sys.stdout.write(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
UnicodeEncodeError: 'ascii' codec can't encode character u'\xa6' in position 0: ordinal not in range(128)

抛出错误。我在顶部链接的文章中提到,这是因为默认的控制台编码是“ascii”。但是,在我的情况下并不是这样:

>>> sys.stdout.encoding
'UTF-8'

那么对于这里发生的情况,您有什么想法并且如何解决这个问题呢?

谢谢 D.


1
在Python 2.7中,使用UTF-8终端编码,一切似乎都正常。你可以尝试使用sys.stdout.write(a.encode("UTF-8")),看看会发生什么? - yasar
没错,那个有效了...糟糕,我刚意识到我使用了错误的Python版本来生成样本。我应该使用2.6.5。那么为什么会发生这种情况呢?是在2.7之前的Python中出现了一个错误吗? - Dmitry B.
显然,当尝试写入stdout时,你的Python会尝试使用ascii编码你的unicode对象,但是却失败了。我不确定为什么,但我的Python没有这样做 :) - yasar
1个回答

12

这是一个长期存在的错误,已在Python 2.7中进行了修复,但由于太晚,无法向Python 2.6回溯。

文档指出,当Unicode字符串写入文件时,应该使用file.encoding将其转换为字节字符串。但是,sys.stdout并没有遵循这个规定,而是使用默认的Unicode编码。通常情况下,这被设置为“ascii”(通过site模块),但可以使用sys.setdefaultencoding更改:

Python 2.6.7 (r267:88850, Aug 14 2011, 12:32:40) [GCC 4.6.2] on linux3
>>> a = u'\xa6\n'
>>> sys.stdout.write(a)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec cant encode character u'\xa6' ...
>>> reload(sys).setdefaultencoding('utf8')
>>> sys.stdout.write(a)
¦

然而,更好的解决方案可能是用包装器替换sys.stdout

class StdOut(object):
    def write(self, string):
        if isinstance(string, unicode):
            string = string.encode(sys.__stdout__.encoding)
        sys.__stdout__.write(string)

>>> sys.stdout = StdOut()
>>> sys.stdout.write(a)
¦

标准输出流(stdout)有许多不同的功能(close,flush等)。在这里仅替换write函数会更好。 - halflings

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接