Кажется, что все ответы пока что от пользователей Unix, которые полагают, что консоль Windows похожа на терминал Unix, которого нет.
Проблема заключается в том, что вы не можете выводить выходные данные Unicode на консоль Windows, используя обычные функции ввода-вывода файлов. Необходимо использовать API Windows WriteConsole
. Вероятно, Python должен делать это прозрачно, но это не так.
Существует другая проблема, если вы перенаправляете вывод в файл: текстовые файлы Windows исторически находятся в кодовой странице ANSI, а не в Unicode. Вы можете смело писать UTF-8 в текстовые файлы в Windows в эти дни, но Python этого не делает по умолчанию.
Я думаю, что он должен делать это, но вот какой-то код, чтобы это произошло. Вам не нужно беспокоиться о деталях, если вы этого не хотите; просто вызовите ConsoleFile.wrap_standard_handles(). Вам необходимо установить PyWin, чтобы получить доступ к необходимым API.
import os, sys, io, win32api, win32console, pywintypes
def change_file_encoding(f, encoding):
"""
TextIOWrapper is missing a way to change the file encoding, so we have to
do it by creating a new one.
"""
errors = f.errors
line_buffering = f.line_buffering
# f.newlines is not the same as the newline parameter to TextIOWrapper.
# newlines = f.newlines
buf = f.detach()
# TextIOWrapper defaults newline to \r\n on Windows, even though the underlying
# file object is already doing that for us. We need to explicitly say "\n" to
# make sure we don't output \r\r\n; this is the same as the internal function
# create_stdio.
return io.TextIOWrapper(buf, encoding, errors, "\n", line_buffering)
class ConsoleFile:
class FileNotConsole(Exception): pass
def __init__(self, handle):
handle = win32api.GetStdHandle(handle)
self.screen = win32console.PyConsoleScreenBufferType(handle)
try:
self.screen.GetConsoleMode()
except pywintypes.error as e:
raise ConsoleFile.FileNotConsole
def write(self, s):
self.screen.WriteConsole(s)
def close(self): pass
def flush(self): pass
def isatty(self): return True
@staticmethod
def wrap_standard_handles():
sys.stdout.flush()
try:
# There seems to be no binding for _get_osfhandle.
sys.stdout = ConsoleFile(win32api.STD_OUTPUT_HANDLE)
except ConsoleFile.FileNotConsole:
sys.stdout = change_file_encoding(sys.stdout, "utf-8")
sys.stderr.flush()
try:
sys.stderr = ConsoleFile(win32api.STD_ERROR_HANDLE)
except ConsoleFile.FileNotConsole:
sys.stderr = change_file_encoding(sys.stderr, "utf-8")
ConsoleFile.wrap_standard_handles()
print("English 漢字 Кири́ллица")
Это немного сложнее: если стандартный вывод или STDERR это консоль, необходимо вывести с WriteConsole; но если это не (например, файл foo.py>), это не сработает, и нам нужно вместо этого изменить кодировку файла на UTF-8.
Противоположность в любом случае не будет работать. Вы не можете выводить в обычный файл с помощью WriteConsole (это не байтовый API, а UTF-16, PyWin скрывает эту деталь), и вы не можете писать UTF-8 на консоль Windows.
Также нужно использовать _get_osfhandle для получения дескриптора stdout и stderr, вместо того, чтобы предполагать, что они назначены стандартным дескрипторам, но у этого API нет привязки к PyWin.
См. Http://stackoverflow.com/questions/5419/python-unicode-and-the-windows-console - и, в конечном счете, см .: http://wiki.python.org/moin/PrintFails - я думаю, что это что вы ищете. – Thanatos
Thanatos правильный - это ошибка печати. Мне грустно. Я думал, что Python прост в использовании :( –
Оказывается, проблема в том, что это не связано с файлами - поддержка Unicode в Python 3 на Windows немного неоднородна - печать не работает в консоли, и файлы открываются в не-utf режиме (это был другой метод, который я пробовал перед отправкой здесь), поэтому у меня, казалось бы, не было вариантов сбрасывать то, что я просматривал. В дополнение к принятому ответу я также мог перепрыгнуть через кодеки.открыть обруч, чтобы создать файл, который представляет тип текста по умолчанию в Python, и посмотрел на это. Как непитонический. –