Вопрос-Ответ

Python, Unicode, and the Windows console

Python, Unicode и консоль Windows

Когда я пытаюсь ввести print строку в консоли Windows, иногда я получаю сообщение об ошибкеUnicodeEncodeError: 'charmap' codec can't encode character ..... Я предполагаю, что это связано с тем, что консоль Windows не может обрабатывать все символы Unicode.

Как я могу обойти это? Например, как я могу заставить программу отображать символ замены (например, ?) вместо сбоя?

Переведено автоматически
Ответ 1

Обновление для Python 3.6 : реализует PEP 528: Измените кодировку консоли Windows на UTF-8: консоль по умолчанию в Windows теперь будет принимать все символы Unicode. Внутри он использует тот же Unicode API, что и в win-unicode-console пакете, упомянутом ниже. print(unicode_string) теперь он должен работать.



Я получаю UnicodeEncodeError: 'charmap' codec can't encode character... ошибку.


Ошибка означает, что символы Unicode, которые вы пытаетесь напечатать, не могут быть представлены с использованием текущей (chcp) кодировки символов консоли. Кодовая страница часто имеет 8-разрядную кодировку, такую как cp437, которая может представлять только ~ 0x100 символов из ~ 1 МЛН символов Unicode:

>>> u"\N {ЗНАК ЕВРО}".encode('cp437')
Обратная трассировка (последний последний вызов):
...
Ошибка UnicodeEncodeError: кодек 'charmap' не может закодировать символ '\ u20ac' в позиции 0:
сопоставление символов с

Я предполагаю, что это связано с тем, что консоль Windows не принимает символы только для Unicode. Как лучше всего обойти это?


Консоль Windows принимает символы Unicode и даже может отображать их (только BMP) если настроен соответствующий шрифт. WriteConsoleW() Следует использовать API, как предложено в ответе @Daira Hopwood. Он может вызываться прозрачно, т. Е. вам не нужно и не следует изменять свои скрипты, если вы используете win-unicode-console package:

T:\> py -m pip install win-unicode-console
T:\> py -m run your_script.py

Смотрите В чем дело с Python 3.4, Unicode, разными языками и Windows?


Есть ли какой-нибудь способ заставить Python автоматически печатать ? вместо сбоя в этой ситуации?


Если в вашем случае достаточно заменить все неэнкодируемые символы на ? , то вы могли бы установить PYTHONIOENCODING envvar:

T:\> set PYTHONIOENCODING=:replace
T:\> python3 -c "print(u'[\N{EURO SIGN}]')"
[?]

В Python 3.6+ кодировка, указанная в PYTHONIOENCODING envvar, игнорируется для буферов интерактивной консоли, если только для PYTHONLEGACYWINDOWSIOENCODING envvar не задано значение непустой строки.

Ответ 2

Примечание: Этот ответ отчасти устарел (с 2008 года). Пожалуйста, используйте приведенное ниже решение с осторожностью!!


Вот страница , на которой подробно описывается проблема и решение (найдите на странице текст , переносящий sys.stdout в экземпляр):

PrintFails - Python Wiki

Вот отрывок кода с этой страницы:

$ python -c 'import sys, codecs, locale; print sys.stdout.encoding; \
sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout); \
line = u"\u0411\n"; print type(line), len(line); \
sys.stdout.write(line); print line'

UTF-8
<type 'unicode'> 2
Б
Б

$ python -c 'import sys, codecs, locale; print sys.stdout.encoding; \
sys.stdout = codecs.getwriter(locale.getpreferredencoding())(sys.stdout); \
line = u"\u0411\n"; print type(line), len(line); \
sys.stdout.write(line); print line'
| cat
None
<type 'unicode'> 2
Б
Б

На этой странице есть еще кое-какая информация, которую стоит прочитать.

Ответ 3

Обновление: На Python 3.6 или более поздней версии печать строк Unicode в консоли Windows просто работает.

Итак, обновите Python до последней версии, и все готово. На этом этапе я рекомендую использовать 2to3 для обновления вашего кода до Python 3.x, если это необходимо, и просто отказаться от поддержки Python 2.x. Обратите внимание, что ни для одной версии Python до 3.7 (включая Python 2.7) не было поддержки безопасности с декабря 2021 года.

Если вам действительно все еще нужна поддержка более ранних версий Python (включая Python 2.7), вы можете использовать https://github.com/Drekin/win-unicode-console , который основан на тех же API, что и код в ответе, который был ранее связан здесь, и использует те же API, что и код в ответе. (Эта ссылка содержит некоторую информацию о конфигурации шрифтов Windows, но я сомневаюсь, что она все еще применима к Windows 8 или более поздней версии.)

Примечание: несмотря на другие правдоподобно звучащие ответы, предлагающие изменить кодовую страницу на 65001, это не работало до Python 3.8. (С тех пор это вроде как работает, но, как указывалось выше, вам все равно не нужно этого делать для Python 3.6+.) Кроме того, изменение кодировки по умолчанию с помощью sys.setdefaultencoding является (по-прежнему) не очень хорошей идеей.

Ответ 4

Если вы не заинтересованы в получении надежного представления плохих символов, вы можете использовать что-то вроде этого (работа с python > = 2.6, включая 3.x):

from __future__ import print_function
import sys

def safeprint(s):
try:
print(s)
except UnicodeEncodeError:
if sys.version_info >= (3,):
print(s.encode('utf8').decode(sys.stdout.encoding))
else:
print(s.encode('utf8'))

safeprint(u"\N{EM DASH}")

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

python unicode