Подтвердить что ты не робот

UnicodeEncodeError: кодек ascii не может кодировать символ в позиции 0: порядковый номер не в диапазоне (128)

Я работаю над Python script, который использует ножничный символ (9986 - ✂), и я пытаюсь перенести свой код на Mac, но я столкнулся с этой ошибкой.

При работе от IDLE (Python 3.2.5 - OS X 10.4.11 iBook G4 PPC) символ дескриптора отображается отлично, и код работает полностью на Ubuntu 13.10, но когда я пытаюсь запустить это в терминале, я получаю эта ошибка/трассировка:

Traceback (most recent call last):
  File "snippets-convert.py", line 352, in <module>
    main()
  File "snippets-convert.py", line 41, in main
    menu()
  File "snippets-convert.py", line 47, in menu
    print ("|\t ",snipper.decode(),"PySnipt'd",snipper.decode(),"\t|")
UnicodeEncodeError: 'ascii' codec can't encode character '\u2702' in position 0: ordinal not in range(128)

и код, который дает мне проблему:

print ("|\t ",chr(9986),"PySnipt'd",chr(9986),"\t|")

Не означает ли этот сигнал, что терминал не может отображать этот символ? Я знаю, что это старая система, но в настоящее время это единственная система, которую я должен использовать. Может ли возраст ОС мешать программе?

Я прочитал следующие вопросы:

Что вызывает эту ошибку? Является ли это временем системы/ОС, версией Python или некоторой ошибкой программирования?

ИЗМЕНИТЬ: Эта ошибка появляется позже с этой повторяющейся проблемой (просто подумал, что я добавлю ее, поскольку она находится в одной программе и является той же ошибкой):

Traceback (most recent call last):
  File "snippets-convert.py", line 353, in <module>
    main()
  File "snippets-convert.py", line 41, in main
    menu()
  File "snippets-convert.py", line 75, in menu
    main()
  File "snippets-convert.py", line 41, in main
    menu()
  File "snippets-convert.py", line 62, in menu
    search()
  File "snippets-convert.py", line 229, in search
    print_results(search_returned)      # Print the results for the user
  File "snippets-convert.py", line 287, in print_results
    getPath(toRead)                                             # Get the path for the snippet
  File "snippets-convert.py", line 324, in getPath
    snipXMLParse(path)
  File "snippets-convert.py", line 344, in snipXMLParse
    print (chr(164),child.text)
UnicodeEncodeError: 'ascii' codec can't encode character '\xa4' in position 0: ordinal not in range(128)

EDIT:

Я зашел в настройки символа терминала и фактически поддерживает этот символ (как вы можете видеть на этом скриншоте:

enter image description here

когда я вставляю его в терминал, он выводит это: \342\234\202, и когда я нажимаю Enter, я получаю следующее: -bash: ✂: command not found

EDIT Команды Ran как @J.F. Себастьян спросил:

python3 test-io-encoding.py:

PYTHONIOENCODING:       None
locale(False):  US-ASCII
device(stdout): US-ASCII
stdout.encoding:        US-ASCII
device(stderr): US-ASCII
stderr.encoding:        US-ASCII
device(stdin):  US-ASCII
stdin.encoding: US-ASCII
locale(False):  US-ASCII
locale(True):   US-ASCII

python3 -S test-io-encoding.py:

PYTHONIOENCODING:       None
locale(False):  US-ASCII
device(stdout): US-ASCII
stdout.encoding:        US-ASCII
device(stderr): US-ASCII
stderr.encoding:        US-ASCII
device(stdin):  US-ASCII
stdin.encoding: US-ASCII
locale(False):  US-ASCII
locale(True):   US-ASCII

EDIT Пробовал "хакерское" решение, предоставленное @PauloBu:

Как вы можете видеть, это вызвало одно (Yay!) scissor, но теперь я получаю новую ошибку. Traceback/ошибка:

+-=============================-+
✂Traceback (most recent call last):
  File "snippets-convert.py", line 357, in <module>
    main()
  File "snippets-convert.py", line 44, in main
    menu()
  File "snippets-convert.py", line 52, in menu
    print("|\t "+sys.stdout.buffer.write(chr(9986).encode('UTF-8'))+" PySnipt'd "+ sys.stdout.buffer.write(chr(9986).encode('UTF-8'))+" \t|")
TypeError: Can't convert 'int' object to str implicitly

EDIT Добавлены результаты исправления @PauloBu:

+-=============================-+
|
✂ PySnipt'd 
✂       |
+-=============================-+

ИЗМЕНИТЬ

И его исправление для его исправления:

+-=============================-+
✂✂|       PySnipt'd     |
+-=============================-+
4b9b3361

Ответ 1

Когда Python печатает и выводит, он автоматически кодирует его на целевой носитель. Если это файл, UTF-8 будет использоваться по умолчанию, и все будут довольны, но если это терминал, Python выяснит кодировку, которую использует терминал, и попытается кодировать вывод с помощью этого.

Это означает, что если ваш терминал использует ascii в качестве кодировки, Python пытается закодировать scissor char на ascii. Конечно, ascii не поддерживает его, поэтому вы получаете ошибку декодирования Unicode.

Вот почему вам всегда нужно явно кодировать ваш вывод. Явное лучше, чем неявное запоминание? Чтобы исправить свой код, вы можете:

import sys
sys.stdout.buffer.write(chr(9986).encode('utf8'))

Это кажется немного хакерским. Вы также можете установить PYTHONIOENCODING = utf-8 перед выполнением script. Мне неудобно работать с обоими решениями. Вероятно, ваша консоль не поддерживает utf-8, и вы видите тарабарщину. Но ваша программа будет вести себя правильно.

Что я настоятельно рекомендую, если вам нужно определенно показать правильный вывод на консоли, чтобы настроить консоль на использование другой кодировки, поддерживающей символ scissor. (возможно, utf-8). В Linux это можно добиться, выполнив: export lang=UTF_8. В Windows вы меняете страницу кода консоли с помощью chcp. Просто выясните, как установить utf8 в вашем и IMHO, что будет лучшим решением.


Вы не можете смешивать print и sys.stdout.write, потому что они в основном одинаковы. Что касается вашего кода, хакерский способ будет таким:
sys.stdout.buffer.write(("|\t "+ chr(9986) +" PySnipt'd " + chr(9986)+" \t|").encode('utf8'))

Я предлагаю вам прочитать в документах, чтобы узнать, что происходит под капотом с помощью функции print и sys.stdout: http://docs.python.org/3/library/sys.html#sys.stdin

Надеюсь, это поможет!

Ответ 2

test_io_encoding.py выводит, что вы должны изменить настройки locale, например, установить LANG=en_US.UTF-8.


Первая ошибка может быть вызвана тем, что вы пытаетесь декодировать строку, которая уже является Unicode. Python 2 пытается кодировать его с использованием кодировки по умолчанию ('ascii') перед ее расшифровкой, используя (возможно) различную кодировку символов. Ошибка на шаге encode:

>>> u"\u2702".decode() # Python 2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\u2702' in position 0: ordinal not in range(128)

Похоже, вы используете script, используя Python 2 вместо Python 3. Вы получите:

>>> "\u2702".decode() # Python 3
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'str' object has no attribute 'decode'

другая ошибка.

Просто отпустите вызов .decode():

print("|\t {0} PySnipt'd {0} \t|".format(snipper))

Вторая проблема связана с печатью строки Unicode в трубе:

$ python3 -c'print("\u2702")'
✂
$ python3 -c'print("\u2702")' | cat
Traceback (most recent call last):
  File "<string>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character '\u2702' in position 0: ordinal not in range(128)

Установите для своей цели PYTHONIOENCODING переменную окружения:

$ PYTHONIOENCODING=utf-8 python3 -c'print("\u2702")' | cat
✂

терминал просто показывает это: | b'\xe2\x9c\x82' PySnipt'd b'\xe2\x9c\x82' |

Если snipper является объектом bytes, оставьте вызов snipper.decode().

$ python3 -c"print(b'\xe2\x9c\x82'.decode())"
✂
$ python3 -c"print(b'\xe2\x9c\x82'.decode())" | cat
Traceback (most recent call last):
  File "<string>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character '\u2702' in position 0: ordinal not in range(128)

Исправление одинаково:

$ PYTHONIOENCODING=utf-8 python3 -c"print(b'\xe2\x9c\x82'.decode())" | cat
✂

Ответ 3

В моей локали установлено значение de_AT.UTF-8, но эти строки в /etc/profile отсутствовали:

export LANG=de_AT.UTF-8
export LANGUAGE=de_AT.UTF-8
export LC_ALL=de_AT.UTF-8

logout/login и ваша проблема должна быть решена

Чтобы проверить, правильно ли установлены все локали, введите locale в терминале

Выход должен быть похож на этот:

LANG=de_AT.UTF-8
LANGUAGE=de_AT.UTF-8
LC_CTYPE="de_AT.UTF-8"
LC_NUMERIC="de_AT.UTF-8"
LC_TIME="de_AT.UTF-8"
LC_COLLATE="de_AT.UTF-8"
LC_MONETARY="de_AT.UTF-8"
LC_MESSAGES="de_AT.UTF-8"
LC_PAPER="de_AT.UTF-8"
LC_NAME="de_AT.UTF-8"
LC_ADDRESS="de_AT.UTF-8"
LC_TELEPHONE="de_AT.UTF-8"
LC_MEASUREMENT="de_AT.UTF-8"
LC_IDENTIFICATION="de_AT.UTF-8"
LC_ALL=de_AT.UTF-8

Ответ 4

в первой строке вашего файла .py вам нужно добавить эту строку:

# - кодирование: utf-8 -

и вы также можете попробовать следующее:

print ( "|\t", unichr (9986), "PySnipt'd", unichr (9986), "\ t |" )