Настройте кодировку потока Python - PullRequest
0 голосов
/ 14 февраля 2019

Есть ли способ (на python2 и python3) настроить tmp_stdout на использование другой кодировки?

(я знаю, что на python3 есть параметр кодирования, но на python2 это невозможно)

import tempfile
import sys

original_stdout = sys.stdout

with tempfile.TemporaryFile(mode="w+") as tmp_stdout:
    # patch sys.stdout  
    sys.stdout = tmp_stdout

    print("?")
    tmp_stdout.seek(0)
    actual_output = tmp_stdout.read()

# restore stdout
sys.stdout = original_stdout

Кроме того, почему используется кодировка по умолчанию для windows cp1252, даже когда моя командная строкаusese cp850.

Это ошибка, которую вы получаете, когда запускаете ее в Windows с python3.6

Traceback (most recent call last):
  File "Desktop\test.py", line 11, in <module>
    print("?")
  File "C:\Users\AppData\Local\Programs\Python\Python36\lib\tempfile.py", line 483, in func_wrapper
    return func(*args, **kwargs)
  File "C:\Users\AppData\Local\Programs\Python\Python36\lib\encodings\cp1252.py", line 19, in encode
    return codecs.charmap_encode(input,self.errors,encoding_table)[0]
UnicodeEncodeError: 'charmap' codec can't encode character '\U0001f4d9' in position 0: character maps to <undefined>

1 Ответ

0 голосов
/ 17 февраля 2019

По умолчанию в консоли 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...