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

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

Изменить: я использую Python 2.5.


Примечание: @ LasseV.Karlsen ответ с галочкой устарел (с 2008 года). Пожалуйста, используйте решения / ответы / предложения ниже с осторожностью!

Ответ @JFSebastian более актуален на сегодняшний день (6 января 2016 года).

7.08.2008 22:26:58
На какой версии Python вы работаете? Я видел ссылки, что это было сломано в 2.4.3 и исправлено в 2.4.4.
Stu 7.08.2008 22:30:38
связанные с : bugs.python.org/issue1602
jfs 4.01.2012 22:51:43
проверить это .
Soorena 18.09.2016 13:22:04
самый простой ответ, который я нашел, это набрать: chcp 65001 перед использованием pyhton в cmd
Soorena 28.09.2016 09:50:16
Тогда вы должны изменить свой принятый ответ ...
Mr_and_Mrs_D 20.02.2018 09:46:48
13 ОТВЕТОВ
РЕШЕНИЕ

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


Вот страница, которая детализирует проблему и решение (найдите на странице текст Wrapping 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
  Б
  Б

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

37
4.01.2016 17:18:53
Ссылка мертва, а суть ответа не указана. -1
0xC0000022L 11.01.2013 14:12:46
Когда я пробую данный совет по упаковке sys.stdout, он печатает неправильные вещи. Например, u'\u2013'становится ûвместо черты.
user2357112 supports Monica 12.07.2014 22:39:53
@ user2357112 Вам придется опубликовать новый вопрос об этом. Unicode и системная консоль не обязательно являются лучшей комбинацией, но я не знаю достаточно об этом, поэтому, если вам нужен определенный ответ, опубликуйте вопрос здесь на SO об этом.
Lasse V. Karlsen 13.07.2014 12:05:21
ссылка мертва Пример кода не подходит для консоли Windows, где кодовая страница (OEM), такая как cp437, отличается от кодовой страницы Windows ANSI, такой как cp1252. Код не исправляет UnicodeEncodeError: 'charmap' codec can't encode characterошибку и может привести к mojibake, например, ا©молча заменяется на ╪º⌐.
jfs 24.08.2015 07:55:58

Причиной вашей проблемы НЕ является консоль Win, которая не желает принимать Unicode (так как она делает это, так как я предполагаю, что Win2k по умолчанию). Это системная кодировка по умолчанию. Попробуйте этот код и посмотрите, что он вам дает:

import sys
sys.getdefaultencoding()

если он говорит ascii, у вас есть причина ;-) Вы должны создать файл с именем sitecustomize.py и поместить его в путь к Python (я поместил его в /usr/lib/python2.5/site-packages, но это отличается от Win - это c: \ python \ lib \ site-packages или что-то еще) со следующим содержимым:

import sys
sys.setdefaultencoding('utf-8')

и, возможно, вы захотите указать кодировку в ваших файлах:

# -*- coding: UTF-8 -*-
import sys,time

Изменить: больше информации можно найти в превосходной книге «Погружение в Python»

2
4.12.2012 01:52:54
setdefaultencoding () больше не используется в sys (начиная с версии 2.0 в соответствии с документами модуля).
Jon Cage 4.11.2008 15:53:37
Я не могу доказать это прямо сейчас, но я знаю, что я использовал этот трюк в более поздней версии - 2.5 в Windows.
Bartosz Radaczyński 9.04.2009 21:11:41
Хорошо, через некоторое время я обнаружил, что: «Эта функция предназначена только для реализации модуля сайта и, при необходимости, для sitecustomize. После использования модулем сайта она удаляется из пространства имен модуля sys. "
Bartosz Radaczyński 30.05.2009 20:43:40
на самом деле вы можете установить консоль Windows для UTF-8. Вы должны сказать chcp 65001, и это будет Unicode.
Bartosz Radaczyński 28.09.2010 19:25:41
Чтобы было абсолютно ясно: менять кодировку по умолчанию очень плохая идея . Это похоже на то, как если бы вы сломали ногу и пошли дальше, как будто ничего не произошло, вместо того, чтобы врач правильно установил кости. Весь код, обрабатывающий текст Unicode, должен делать это последовательно, а не полагаться на неявное кодирование / декодирование.
Martijn Pieters♦ 18.12.2014 23:19:01

Приведенный ниже код выведет Python на консоль как UTF-8 даже в Windows.

Консоль будет хорошо отображать символы в Windows 7, но в Windows XP она будет отображаться не очень хорошо, но, по крайней мере, она будет работать, и самое главное, вы получите согласованный вывод из своего сценария на всех платформах. Вы сможете перенаправить вывод в файл.

Ниже код был протестирован с Python 2.6 на Windows.


#!/usr/bin/python
# -*- coding: UTF-8 -*-

import codecs, sys

reload(sys)
sys.setdefaultencoding('utf-8')

print sys.getdefaultencoding()

if sys.platform == 'win32':
    try:
        import win32console 
    except:
        print "Python Win32 Extensions module is required.\n You can download it from https://sourceforge.net/projects/pywin32/ (x86 and x64 builds are available)\n"
        exit(-1)
    # win32console implementation  of SetConsoleCP does not return a value
    # CP_UTF8 = 65001
    win32console.SetConsoleCP(65001)
    if (win32console.GetConsoleCP() != 65001):
        raise Exception ("Cannot set console codepage to 65001 (UTF-8)")
    win32console.SetConsoleOutputCP(65001)
    if (win32console.GetConsoleOutputCP() != 65001):
        raise Exception ("Cannot set console output codepage to 65001 (UTF-8)")

#import sys, codecs
sys.stdout = codecs.getwriter('utf8')(sys.stdout)
sys.stderr = codecs.getwriter('utf8')(sys.stderr)

print "This is an Е乂αmp١ȅ testing Unicode support using Arabic, Latin, Cyrillic, Greek, Hebrew and CJK code points.\n"
10
12.01.2013 20:45:44
Есть ли способ избежать этого, просто используя другую консоль?
endolith 16.04.2011 13:08:19
@sorin: Почему вы сначала import win32consoleза пределами tryа потом вы делаете это условно внутри try? Разве это не бессмысленно (первое import)
0xC0000022L 11.01.2013 14:17:11
Что бы это ни стоило, работает тот, который предоставил Дэвид-Сара Хопвуд (я даже не запустил его, потому что не удосужился установить модуль расширений win32)
Jaykul 10.02.2013 04:11:58
Не меняйте кодировку системы по умолчанию; вместо этого исправьте значения Unicode. Изменение кодировки по умолчанию может нарушить работу библиотек, которые зависят от поведения по умолчанию . Есть причина, по которой вам необходимо принудительно перезагрузить модуль, прежде чем вы сможете это сделать.
Martijn Pieters♦ 15.05.2014 11:36:58

Несмотря на другие правдоподобные ответы, которые предлагают изменить кодовую страницу на 65001, это не работает . (Кроме того , изменение кодировки по умолчанию , используя sys.setdefaultencodingэто не очень хорошая идея .)

Смотрите этот вопрос для деталей и кода, который работает.

27
23.05.2017 12:26:33
win-unicode-consoleПакет Python (на основе вашего кода) позволяет избежать изменения вашего скрипта, если он печатает Unicode напрямую с помощью py -mrun your_script.pyкоманды .
jfs 27.02.2016 14:31:48

Если вы не заинтересованы в надежном представлении плохих символов, вы можете использовать что-то вроде этого (работа с 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.

12
19.05.2012 18:48:28
.encode('utf8').decode(sys.stdout.encoding)приводит к mojibake, например, u"\N{EM DASH}".encode('utf-8').decode('cp437')->ΓÇö
jfs 24.08.2015 07:39:11
Просто print(s.encode('utf-8'))может быть лучший способ избежать ошибок компилятора. Вместо этого вы получаете вывод \ xNN для непечатаемых символов, чего было достаточно для моих диагностических сообщений.
CODE-REaD 14.05.2016 17:25:41
Это чрезвычайно, невероятно неправильно. Кодирование в UTF-8 с последующим декодированием в виде 8-битной кодировки будет а) часто давать сбой, не во всех кодовых страницах есть символы для всех 256-байтовых значений, и б) всегда неправильная интерпретация данных, вместо этого возникает беспорядок в Мохибаке .
Martijn Pieters♦ 13.01.2017 18:08:28

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


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

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

>>> u "\ N {EURO SIGN}". encode ('cp437')
Traceback (последний вызов был последним):
...
UnicodeEncodeError: кодек 'charmap' не может кодировать символ '\ u20ac' в позиции 0:
карты персонажей 

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

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

T:\> py -mpip install win-unicode-console
T:\> py -mrun your_script.py

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

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

Если ?в вашем случае достаточно заменить все не кодируемые символы на, то вы можете установить PYTHONIOENCODINGenvvar :

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

В Python 3.6+ кодировка, заданная PYTHONIOENCODINGenvvar, игнорируется для буферов интерактивной консоли, если для PYTHONLEGACYWINDOWSIOENCODINGenvvar не задана непустая строка.

72
23.05.2017 12:10:44
«Консоль по умолчанию в Windows теперь будет принимать все символы Юникода», НО вам нужно настроить консоль: щелкните правой кнопкой мыши в верхней части окна (в окне cmd или python IDLE), в default / font выберите «Консоль Lucida». (Японский и китайский не работают для меня, но я должен выжить без этого ...)
JinSnow 13.01.2017 20:46:11
@Guillaume: ответ содержит выделенную жирным шрифтом фразу о консоли Windows: «если настроен соответствующий шрифт». В этом ответе не упоминается IDLE, но вам не нужно настраивать в нем шрифт (по умолчанию я вижу японские и китайские символы в IDLE. Отлично print('\u4E01'), попробуйте , print('\u6b63')).
jfs 13.01.2017 21:14:04
@Guillaume Вы даже можете получить китайский язык, если установите языковой пакет в Windows 10. В него добавлены консольные шрифты, которые поддерживают китайский.
Mark Tolonen 12.03.2017 18:27:35

В некотором роде ответ на вопрос Я. Ф. Себастьяна, но более прямой.

Если у вас возникла эта проблема при печати на консоль / терминал, сделайте следующее:

>set PYTHONIOENCODING=UTF-8
1
16.12.2015 07:53:43
set PYTHONIOENCODING=UTF-8может привести к mojibake, если консоль использует другую кодировку, такую ​​как cp437. cp65001имеет различные проблемы . Чтобы распечатать Unicode на консоли Windows, следует использовать Unicode API ( WriteConsoleW()), как предложено в моем ответе, где PYTHONIOENCODINGиспользуется только для замены символов, которые не могут быть представлены в текущей кодовой странице OEM, ?( WriteConsoleW()работает даже для таких символов). PYTHONIOENCODINGможет использоваться, если вывод перенаправлен в файл.
jfs 26.12.2015 03:40:37

Как и ответ Джампаоло Родолы, но еще более грязный: я действительно, действительно собираюсь потратить много времени (в ближайшее время) на понимание всего предмета кодировок и того, как они применяются к консолям Windoze,

На данный момент я просто хотел использовать sthg, что означало бы, что моя программа НЕ РАБОТАЕТ, и что я понял ... а также не требует импорта слишком большого количества экзотических модулей (в частности, я использую Jython, поэтому половину времени занимает Python модуль оказывается фактически не доступен).

def pr(s):
    try:
        print(s)
    except UnicodeEncodeError:
        for c in s:
            try:
                print( c, end='')
            except UnicodeEncodeError:
                print( '?', end='')

NB "pr" короче, чем "print" (и немного короче, чем "safeprint") ...!

5
9.03.2016 22:14:15
Умный, быстрый и грязный способ обойти проблему. Я думаю, что это отлично подходит для прерывистого решения.
JFA 1.07.2016 20:23:12

Джеймс Сулак спросил,

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

Другие решения рекомендуют попытаться изменить среду Windows или заменить print()функцию Python . Ответ ниже приближается к выполнению запроса Сулака.

В Windows 7 Python 3.5 можно заставить печатать Unicode, не выдавая UnicodeEncodeErrorследующее:

    Вместо:     print(text)
    заменить     print(str(text).encode('utf-8'))

Вместо создания исключения Python теперь отображает непечатаемые символы Юникода в виде шестнадцатеричных кодов \ xNN , например:

  Halmalo n \ xe2 \ x80 \ x99 \ xc3 \ xa9tait plus qu \ xe2 \ x80 \ x99un точка нуар

Вместо того

  Halmalo n'était plus qu'un point noir

Конечно, последний предпочтительнее при прочих равных условиях , но в остальном он совершенно точен для диагностических сообщений. Поскольку он отображает Unicode в виде буквенных значений байтов, первый также может помочь в диагностике проблем кодирования / декодирования.

Примечание:str() вызов выше необходимо , потому что в противном случае encode()приводит к Python , чтобы отклонить символ Unicode как кортеж чисел.

0
24.05.2016 16:19:05

Python 3.6 windows7: есть несколько способов запустить python, вы можете использовать консоль python (на которой есть логотип python) или консоль windows (на ней написано cmd.exe).

Я не мог печатать символы utf8 в консоли Windows. Печать символов utf-8 выдает мне эту ошибку:

OSError: [winError 87] The paraneter is incorrect 
Exception ignored in: (_io-TextIOwrapper name='(stdout)' mode='w' ' encoding='utf8') 
OSError: [WinError 87] The parameter is incorrect 

После попыток и не понять ответ выше, я обнаружил, что это была только проблема установки. Щелкните правой кнопкой мыши в верхней части окна консоли cmd, на вкладке выберите fontконсоль lucida.

1
11.05.2017 20:08:34

Для Python 2 попробуйте:

print unicode(string, 'unicode-escape')

Для Python 3 попробуйте:

import os
string = "002 Could've Would've Should've"
os.system('echo ' + string)

Или попробуйте win-unicode-console:

pip install win-unicode-console
py -mrun your_script.py
3
17.01.2018 05:07:50

TL; DR:

print(yourstring.encode('ascii','replace'));

Я сам столкнулся с этим, работая над ботом Twitch chat (IRC). (Последняя версия Python 2.7)

Я хотел разобрать сообщения чата, чтобы ответить ...

msg = s.recv(1024).decode("utf-8")

но также безопасно распечатайте их на консоли в удобочитаемом формате:

print(msg.encode('ascii','replace'));

Это исправило проблему с UnicodeEncodeError: 'charmap'ошибками броска бота и заменило символы юникода на ?.

2
1.07.2018 15:52:05

Просто введите этот код в командной строке перед выполнением скрипта Python:

chcp 65001 & set PYTHONIOENCODING=utf-8
5
2.10.2018 22:11:03