Python 3, использует ли sys.stdout.buffer.write () хороший стиль? - PullRequest
6 голосов
/ 12 июня 2009

После того, как я узнал о чтении файлов юникода в веб-скрипте Python 3.0, теперь пришло время научиться использовать print() с юникодом.

Я искал для написания Unicode, например этот вопрос объясняет, что вы не можете писать символы Unicode в консоли не-Unicode. Однако в моем случае выходные данные передаются в Apache, и я уверен, что он способен обрабатывать текст Unicode. Однако по какой-то причине stdout моего веб-скрипта находится в ascii.

Очевидно, что если бы я сам открывал файл для записи, я бы сделал что-то вроде

open(filename, 'w', encoding='utf8')

но так как мне дали открытый поток, я прибег к использованию

sys.stdout.buffer.write(mytext.encode('utf-8'))

и все, кажется, работает. Это нарушает какое-то правило хорошего поведения или имеет какие-то непредвиденные последствия?

Ответы [ 2 ]

7 голосов
/ 12 июня 2009

Я не думаю, что вы нарушаете какое-либо правило, но

sys.stdout = codecs.EncodedFile(sys.stdout, 'utf8')

похоже, что это может быть удобнее / менее неуклюже.

Редактировать: согласно комментариям, это не совсем правильно - @Miles дал правильный вариант (спасибо!):

sys.stdout = codecs.getwriter('utf8')(sys.stdout.buffer) 

Редактировать: если вы можете настроить переменную окружения PYTHONIOENCODING на utf8, когда Apache запускает ваш скрипт, это было бы еще лучше, если бы sys.stdout автоматически установил utf8; но если это невозможно или нецелесообразно, решение codecs остается в силе.

1 голос
/ 31 августа 2016

Это старый ответ, но я добавлю свою версию здесь, так как я впервые рискнул здесь, прежде чем найти свое решение.

Одна из проблем с codecs.getwriter заключается в том, что если вы выполняете своего рода скрипт, выходные данные будут буферизироваться (тогда как обычно python stdout печатает после каждой строки).

sys.stdout в консоли - это IOTextWrapper, поэтому мое решение использует это. Это также позволяет вам установить line_buffering = True или False.

Например, чтобы установить стандартный вывод вместо кодирования с обратным слешем для всех выходных данных:

sys.stdout = io.TextIOWrapper(sys.stdout.detach(), encoding=sys.stdout.encoding,
                              errors="backslashreplace", line_buffering=True)

Для принудительного использования определенной кодировки (в данном случае utf8):

sys.stdout = io.TextIOWrapper(sys.stdout.detach(), encoding="utf8",
                              line_buffering=True)

Примечание: вызов sys.stdout.detach () закроет базовый буфер. Некоторые модули используют sys.__stdout__, который является просто псевдонимом для sys.stdout, поэтому вы можете также установить это

sys.stdout = sys.__stdout__ = io.TextIOWrapper(sys.stdout.detach(), encoding=sys.stdout.encoding, errors="backslashreplace", line_buffering=True)
sys.stderr = sys.__stderr__ = io.TextIOWrapper(sys.stderr.detach(), encoding=sys.stdout.encoding, errors="backslashreplace", line_buffering=True)
...