кириллица - unicode encode error python 3




Как напечатать utf-8 на консоль с Python 3.4(Windows 8)? (3)

Я пытаюсь напечатать символы карты utf-8 (♠, ♥, ♦, ♣) из модуля python в консоль Windows

UTF-8 - это байтовая кодировка символов Unicode. ♣ ♥ ♦ ♣ - символы Unicode, которые могут быть воспроизведены в различных кодировках, и UTF-8 является одной из этих кодировок - как UTF, UTF-8 может воспроизводить любой символ Unicode. Но в этих персонажах нет ничего особенного «UTF-8».

Другими кодировками, которые могут воспроизводить символы ♣ ♥ ♦ ♣, являются кодовые страницы Windows 850 и 437 , которые ваша консоль, вероятно, будет использовать при установке Windows в Западной Европе. Вы можете напечатать ♠ в этих кодировках, но вы не используете для этого UTF-8, и вы не сможете использовать другие символы Юникода, которые доступны в UTF-8, но выходят за рамки этих кодовых страниц.

print(u'♠')
UnicodeEncodeError: 'charmap' codec can't encode character '\u2660'

В Python 3 это то же самое, что и тест print('♠') вы делали выше, поэтому в том, как вы вызываете скрипт, содержащий этот print , есть кое-что другое по сравнению с вашим py -3.4 . Что sys.stdout.encoding дает вам из сценария?

Для правильной работы print вам нужно убедиться, что Python подбирает правильную кодировку. Если он не делает этого должным образом из настроек терминала, вам действительно нужно установить PYTHONIOENCODING на cp437 .

>>> text = '♠'
>>> print(text.encode('utf-8'))
b'\xe2\x99\xa0'

print может print только строки Unicode. Для других типов, включая строку bytes , полученную из метода encode() , он получает литеральное представление ( repr ) объекта. b'\xe2\x99\xa0' - это как написать 3-байтовый литерал Python, содержащий кодировку UTF-8 ♠.

Если вы хотите обойти неявное кодирование print в PYTHONIOENCODING и заменить свое собственное, вы можете сделать это явно:

>>> import sys
>>> sys.stdout.buffer.write('♠'.encode('cp437'))

Это, конечно, приведет к неправильному выводу для любых консолей, на которых не выполняется кодовая страница 437 (например, не для западноевропейских установок). Как правило, для приложений, использующих C-stdio, как это делает Python, передача не-ASCII-символов в консоль Windows просто слишком ненадежна, чтобы беспокоиться об этом.

Я никогда полностью не зацикливался на кодировании и декодировании юникода в других форматах (utf-8, utf-16, ascii и т. Д.), Но я достиг стены, которая и запутывает, и расстраивает. Я пытаюсь напечатать символы карты utf-8 (♠, ♥, ♦, ♣) из модуля python в консоль Windows. Консоль, которую я использую, это git bash, и я использую console2 в качестве внешнего интерфейса. Я попробовал / прочитал несколько подходов ниже, и пока ничего не получалось. Дайте мне знать, возможно ли то, что я делаю, и правильный способ сделать это.

  • Убедитесь, что консоль может обрабатывать символы utf-8. Эти два теста заставляют меня поверить, что проблема не в консоли.

  • Попытайтесь сделать то же самое из модуля python.
    Когда я выполняю .py, это результат.

    print(u'♠')
    UnicodeEncodeError: 'charmap' codec can't encode character '\u2660' in position 0: character maps to <undefined>
  • Попытка закодировать ♠. Это возвращает мне набор юникодов, закодированный в utf-8, но все еще без символа лопаты.

    text = '♠'
    print(text.encode('utf-8'))
    b'\xe2\x99\xa0'

Я чувствую, что пропускаю шаг или не понимаю весь процесс кодирования / декодирования. Я читал this , this и this . На последней из страниц предлагается включить в код файл sys.stdout, но в this статье говорится, что использование stdout не нужно и указывает на другую страницу с помощью модуля кодеков.

Я весьма озадачен! Я чувствую, как трудно найти качественную документацию по этому вопросу, и, надеюсь, кто-то сможет это выяснить. Любая помощь всегда ценится!

Остин


Вы можете посмотреть на это так. Строка - это последовательность символов, а не последовательность байтов. Символы являются кодовыми точками Unicode. Байты - это просто числа в диапазоне 0–255. На низком уровне компьютеры работают только с последовательностями байтов. Если вы хотите напечатать строку, вы просто вызываете print(a_string) в Python. Но для связи со средой ОС строка должна быть закодирована в виде последовательности байтов. Это делается автоматически где-то под капотами функции print . Используется кодировка sys.stdout.encoding . Если вы получаете UnicodeEncodeError , это означает, что ваши символы не могут быть закодированы с использованием текущей кодировки.

Насколько я знаю, в настоящее время невозможно запустить Python в Windows таким образом, чтобы используемая кодировка могла кодировать каждый символ (как UTF-8 или UTF-16), и оба предполагались Python и действительно использовались ОС среды для ввода и вывода. Существует обходной путь - вы можете использовать пакет win_unicode_console , который призван решить эту проблему. Просто установите его с помощью pip install win_unicode_console , и на вашем сайте sitecustomize его импорт и вызовите win_unicode_console.enable() . Это будет служить внешним патчем для вашей установки Python, вызывающим эту проблему. См. Документацию для получения дополнительной информации: https://github.com/Drekin/win-unicode-console .


По умолчанию консоль в Microsoft Windows отображает только 256 символов (cp437, « 437 », исходный расширенный набор символов ASCII IBM-PC 1981), как вы сказали в комментариях.

а с другой стороны PYTHONIOENCODING по умолчанию установлен в UTF-8 . поэтому я думаю, что если вы хотите напечатать Unicode в Windows, вы должны совместить sys.stdout.encoding и PYTHONIOENCODING вместе!

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

так сделайте что-то вроде этого:

import codecs
my_str='♠' # or something like my_str='\u05dd' 
my_str.encode().decode('cp437')




console