Почему python 2.7 на Windows требует пробела перед символом Unicode при печати?

Я использую cmd Windows, chcp 65001, это мой код:

print u'\u0110 \u0110' + '\n'

Результат:

 (a character cmd can't display) (character what i want)
 Traceback (most recent call last):
      File "b.py", line 26, in <module>
        print u'\u0110 \u0110'
    IOError: [Errno 2] No such file or directory

Но, когда я использую этот код:

print u' \u0110 \u0110' + '\n'

Результат:

(a space)(charecter what i want) (character what i want)
Traceback (most recent call last):
  File "b.py", line 26, in <module>
    print u' \u0110 \u0110' + '\n'
IOError: [Errno 2] No such file or directory

Мой экран: enter image description here

И мой вопрос:

  • Почему python 2.7 нуждается в пробеле при печати символа Unicode?

  • Как исправить IOError: [Errno 2]

Ответ 1

Короткий ответ

В Windows вы не можете печатать произвольные строки с помощью print.

Есть некоторые способы обхода, как показано здесь: Как сделать python 3 print() utf8. Но, несмотря на название этого вопроса, вы не можете использовать это для фактической печати UTF-8 с использованием кодовой страницы 65001, она будет повторять последние несколько байтов после окончания (как я описал дальше)

Пример:

#! python2
import sys

enc = sys.stdout.encoding

def outputUnicode(t):
    bytes = t.encode(enc, 'replace')
    sys.stdout.write(bytes)

outputUnicode(u'The letter \u0110\n')

Длинный ответ

Вы можете изменить кодовую страницу консоли с помощью chcp на кодовую страницу, содержащую символы, которые вы хотите распечатать. Например, в вашем случае запустите chcp 852.

Это результаты в моем поле, если я печатаю следующие строки. Я использую кодовую страницу 850, которая по умолчанию используется для английских систем:

u"\u00abHello\u00bb"  # "«Hello»" 
u"\u0110"  # "Đ"
u"\u4f60\u597d"  # "你好"
u"a\u2192b\u2192c"  # "a→b→c"

Первая команда будет работать, поскольку все символы находятся на кодовой странице 850. Следующие 3 не будут выполнены.

UnicodeEncodeError: 'charmap' codec can't encode character u'\u0110' in position 0: character maps to <undefined>

Измените кодовую страницу на 852, и вторая команда будет работать.

Существует кодовая страница UTF-8 (65001), но она не работает с python 2.7.

В python 3.4 результаты те же. Если вы измените кодовую страницу на 65001, вы получите немного более слабое поведение.

\Python34\python.exe -c "print(u'a\u2192b\u2192c')" a→b→c �c C:\>

Два дополнительных символа ( c) являются следствием нестандартного поведения в стандартной библиотеке C в Windows. Они являются повторением последних 2 байтов в кодировке UTF-8 строки.

Ответ 2

В Windows вы можете печатать произвольные строки с помощью print (пока шрифт может отображать символы). Просто print Юникод и настройте свою среду.

Например, print_unicode.py:

#!/usr/bin/env python
print(u'\u0110\u0110')

Для печати на консоли Windows вы можете использовать win-unicode-console package:

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

Не забудьте настроить соответствующий шрифт консоли. chcp В этом случае значение возврата не имеет значения.

Вы можете вызвать WriteConsoleW() функцию (Unicode API) вручную, чтобы напечатать произвольный текст в консоли Windows.

Вам не нужны сторонние модули, чтобы перенаправить вывод в файл:

T:\> set PYTHONIOENCODING=utf-8
T:\> py print_unicode.py >output-utf-8.txt

Примечание: модуль run не используется. Он работает как на Python 2, так и на 3.

Если вам не нужно печатать символы Unicode, отличные от BMP, тогда вы можете использовать Python IDLE из stdlib, например, в Python 3:

T:\> py -3 -midlelib -r print_unicode.py

IDLE также доступен на Python 2, но вызов отличается.