python中print和sys.stdout.write的unicode处理差异

9 投票
1 回答
3439 浏览
提问于 2025-04-17 05:40

我先说一下,我之前看过这个帖子:关于unicode的奇怪python打印行为,但是那里的解决方案(使用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 个回答

12

这是因为一个长期存在的错误,这个错误在python-2.7中已经被修复,但对于python-2.6来说,修复来得太晚,无法更新。

文档中提到,当将unicode字符串写入文件时,应该使用file.encoding将其转换为字节字符串。但是,sys.stdout并没有遵循这个规则,而是使用了默认的unicode编码。这个默认编码通常是由site模块设置为“ascii”,不过可以通过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)
¦

撰写回答