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|")
Не означает ли этот сигнал, что терминал не может отображать этот символ? Я знаю, что это старая система, но в настоящее время это единственная система, которую я должен использовать. Может ли возраст ОС мешать программе?
Я прочитал следующие вопросы:
-
UnicodeEncodeError: кодек ascii не может кодировать символ u '\ xef' в позиции 0: порядковый номер не в диапазоне (128) - различный символ
-
"кодек UnicodeEncodeError: 'ascii' не может кодировать символ" - использовать 2.6, поэтому не знаю, применяется ли оно
-
UnicodeEncodeError: кодек ascii не может кодировать символ? - Кажется, это правдоподобное решение моей проблемы, .encode('UTF-8')
, я не знаю, t получить ошибку. Однако он отображает код символа, а не тот, который я хочу, и .decode()
просто дает мне ту же ошибку. Не уверен, что я делаю это правильно.
-
UnicodeEncodeError: кодек ascii не может кодировать символы в позиции 0-6: порядковый номер не в диапазоне (128) - не уверен, что это применимо, он использует GUI, получает вход и все на греческом языке.
Что вызывает эту ошибку? Является ли это временем системы/ОС, версией 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 |
+-=============================-+
Ответы
Ответ 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 |" )