возможно привлечь исключение, которое включает неанглийские символы в python 2?

Я пытаюсь повысить исключение в python 2.7.x, который включает в себя unicode в сообщении. Кажется, я не могу заставить его работать.

Не поддерживается или не рекомендуется включать unicode в сообщение msg? Или мне нужно смотреть на sys.stderr?

# -*- coding: utf-8 -*- class MyException(Exception): def __init__(self, value): self.value = value def __str__(self): return self.value def __repr__(self): return self.value def __unicode__(self): return self.value desc = u'something bad with field \u4443' try: raise MyException(desc) except MyException as e: print(u'Inside try block : ' + unicode(e)) # here is what i wish to make work raise MyException(desc) 

Выполняющий скрипт выводит результат ниже. Внутри моей попытки / кроме я могу напечатать строку без проблем.

Моя проблема находится за пределами try / except.

 Inside try block : something bad with field 䑃Traceback (most recent call last): File "C:\Python27\lib\bdb.py", line 387, in run exec cmd in globals, locals File "C:\Users\ghis3080\r.py", line 25, in <module> raise MyException(desc) MyException: something bad with field \u4443 

Заранее спасибо.

Поведение зависит от версии Python и среды. На Python 3 обработчик ошибок кодирования символов для sys.stderr всегда 'backslashreplace' :

 from __future__ import unicode_literals, print_function import sys s = 'unicode "\u2323" smile' print(s) print(s, file=sys.stderr) try: raise RuntimeError(s) except Exception as e: print(e.args[0]) print(e.args[0], file=sys.stderr) raise 

python3:

 $ PYTHONIOENCODING=ascii:ignore python3 raise_unicode.py unicode "" smile unicode "\u2323" smile unicode "" smile unicode "\u2323" smile Traceback (most recent call last): File "raise_unicode.py", line 8, in <module> raise RuntimeError(s) RuntimeError: unicode "\u2323" smile 

python2 :

 $ PYTHONIOENCODING=ascii:ignore python2 raise_unicode.py unicode "" smile unicode "" smile unicode "" smile unicode "" smile Traceback (most recent call last): File "raise_unicode.py", line 8, in <module> raise RuntimeError(s) RuntimeError 

То есть в моей системе сообщение об ошибке употребляется на python2.

Примечание. В Windows вы можете попробовать:

 T:\> set PYTHONIOENCODING=ascii:ignore T:\> python raise_unicode.py 

Для сравнения:

 $ python3 raise_unicode.py unicode "⌣" smile unicode "⌣" smile unicode "⌣" smile unicode "⌣" smile Traceback (most recent call last): File "raise_unicode.py", line 8, in <module> raise RuntimeError(s) RuntimeError: unicode "⌣" smile 

Так работает Python. Я считаю, что то, что вы видите, происходит от traceback._some_string() в основной библиотеке Python. В этом модуле, когда трассировка стека выполняется, код в этом методе сначала пытается преобразовать сообщение, используя str() , а затем, если это вызывает исключение, преобразует сообщение с помощью unicode() , а затем преобразует его в ascii с использованием encode("ascii", "backslashreplace") . Вы получаете достоверный результат, и все работает правильно, я полагаю, что Python делает все возможное, чтобы псевдо-вниз преобразовать сообщение об ошибке, чтобы он отображался без проблем независимо от платформы, выполняющей его. Это всего лишь код юникода для вашего персонажа. Это не происходит в вашем блоке try/except потому что это преобразование является чем-то специфичным для механизма, который создает трассировки стека (например, в случае неперехваченных исключений).

В моем случае ваш пример работал так, как следует, печатая красивый юникод.

Но иногда у вас много проблем со стеком исключений, напечатанными без (или с экранированными / обратными символами) символами юникода. Можно преодолеть препятствие и распечатать обычные сообщения.

Пример проблемы с выходом (Python 2.7, linux):

 # -*- coding: utf-8 -*- desc = u'something bad with field ¾' raise SyntaxError(desc.encode('utf-8', 'replace')) 

Он будет печатать только усеченное или привинченное сообщение:

 ~/.../sources/C_patch$ python SO.py Traceback (most recent call last): File "SO.py", line 25, in <module> raise SyntaxError(desc) SyntaxError 

Чтобы увидеть неизменный юникод, вы можете закодировать его на необработанные байты и подать в объект исключения:

 # -*- coding: utf-8 -*- desc = u'something bad with field ¾' raise SyntaxError(desc.encode('utf-8', 'replace')) 

На этот раз вы увидите полное сообщение:

 ~/.../sources/C_patch$ python SO.py Traceback (most recent call last): File "SO.py", line 3, in <module> raise SyntaxError(desc.encode('utf-8', 'replace')) SyntaxError: something bad with field ¾ 

Вы можете сделать value.encode('utf-8', 'replace') в своем конструкторе, если хотите, но с системным исключением вам придется делать это в выражении raise , как в примере.

Подсказка взята здесь: Преодоление разочарования: правильное использование юникода в python2 (есть большая библиотека со многими помощниками, и все они могут быть удалены до примера выше).