По умолчанию в консоли Windows используется системная кодовая страница OEM (например, 850 в Западной Европе), которая поддерживает устаревшие программы DOS и пакетные сценарии, но в настоящее время не имеет смысла.Python 3.6+ использует вместо этого Unicode API консоли.Внутренне это UTF-16LE, но на уровне буфер / сырье он представлен как UTF-8 для кроссплатформенной совместимости.Чтобы получить аналогичную поддержку в Python 2, установите и включите win_unicode_console .
Для неконсольных файлов кодировкой по умолчанию в Python 3 является системная кодовая страница ANSI (например, 1252 в Западной Европе).Это классическое значение по умолчанию для многих текстовых редакторов в Windows, таких как блокнот.Чтобы получить полный диапазон Unicode, переопределите кодировку, используя аргумент encoding='utf-8'
.Для поддержки этого как в Python 2, так и в 3 вы можете обернуть дескриптор файла (т.е. fileno()
) с помощью модуля io, который был перенесен при выходе Python 3 (2.6+).Например:
import sys
import tempfile
with tempfile.TemporaryFile(mode='w+b') as tmp:
tmp_stdout = io.open(tmp.fileno(), mode='w+', encoding='utf-8', closefd=False)
sys.stdout, original_stdout = tmp_stdout, sys.stdout
try:
print("?")
finally:
sys.stdout = original_stdout
tmp_stdout.seek(0)
actual_output = tmp_stdout.read()
Обратите внимание, что временный файл открывается в режиме "w + b", который позволяет избежать низкоуровневого текстового режима среды выполнения C в Python 2 в Windows, который нам не нуженпотому что он обрабатывает символ 0x1A (то есть Ctrl + Z) как маркер конца файла (наследие от DOS и CP / M) и выполняет перевод новой строки (например, LF -> CRLF).В модуле io TextIOWrapper
уже реализован перевод новой строки.Также обратите внимание, что для вызова io.open
используется closefd=False
, поскольку tmp
уже автоматически закрывается в операторе with
.