Unicode Python обрабатывает различия между print и sys.stdout.write - PullRequest
9 голосов
/ 05 ноября 2011

Начну с того, что я уже видел этот пост: Странное поведение печати на python с использованием 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 Ответ

12 голосов
/ 05 ноября 2011

Это связано с давней ошибкой, которая была исправлена ​​ в python-2.7, но слишком поздно, чтобы перенести ее обратно в python-2.6.

Документация гласит, что когда строки в кодировке Юникод записываются в файл, они должны быть преобразованы в строки байтов с использованием 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)
¦
...