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

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

символ ножниц отлично отображается при запуске из холостого хода (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'), Я не понимаю ошибку. Однако он отображает код символа, а не символ, который я хочу, и .decode() просто дает мне ту же ошибку. Не уверен, что все делаю правильно.

  • UnicodeEncodeError: кодек 'ascii' не может кодировать символы в позиции 0-6: порядковый номер не в диапазоне (128) - не уверен, что это применимо, он использует графический интерфейс, получает ввод и все на греческом языке.

что вызывает эту ошибку? Это возраст системы / ОС, версия 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

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

редактировать 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

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

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

+-=============================-+
✂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

редактировать добавлены результаты @PauloBu исправить:

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

редактировать:

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

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

4 ответов


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

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

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

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

это кажется немного hackerish. Вы также можете установить PYTHONIOENCODING=utf-8 Перед выполнением скрипта. Я не согласен с обоими решениями. Возможно, ваша консоль не поддерживает 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'))

Я предлагаю вам прочитать в документах, чтобы увидеть, что происходит под капотом с


test_io_encoding.py выход предполагает, что вы должны изменить свой locale настройки, например, set 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)

похоже, что вы работаете ваш скрипт использует 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
✂

мой язык установлен в 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

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

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

и Вы тоже можете попробовать это:

print ("|\t", unichr(9986),"Pysnipt'D", unichr (9986),"\t|")