Я бы сделал это так, чтобы изменение его типа foo()
не потребовало также его изменения bar()
.
def foo():
try:
raise IOError('Stuff')
except:
raise
def bar(arg1):
try:
foo()
except Exception as e:
raise type(e)(e.message + ' happens at %s' % arg1)
bar('arg1')
Traceback (most recent call last):
File "test.py", line 13, in <module>
bar('arg1')
File "test.py", line 11, in bar
raise type(e)(e.message + ' happens at %s' % arg1)
IOError: Stuff happens at arg1
Обновление 1
Вот небольшая модификация, которая сохраняет исходную трассировку:
...
def bar(arg1):
try:
foo()
except Exception as e:
import sys
raise type(e), type(e)(e.message +
' happens at %s' % arg1), sys.exc_info()[2]
bar('arg1')
Traceback (most recent call last):
File "test.py", line 16, in <module>
bar('arg1')
File "test.py", line 11, in bar
foo()
File "test.py", line 5, in foo
raise IOError('Stuff')
IOError: Stuff happens at arg1
Обновление 2
Для Python 3.x код в моем первом обновлении синтаксически неверен, плюс идея наличия message
атрибута BaseException
была отозвана при изменении PEP 352 16 мая 2012 г. (мое первое обновление было опубликовано 12 марта 2012 г.) . Итак, в настоящее время в Python 3.5.2 вам все равно нужно будет что-то сделать в этих строках, чтобы сохранить трассировку, а не жестко кодировать тип исключения в функции bar()
. Также обратите внимание, что там будет строка:
During handling of the above exception, another exception occurred:
в отображаемых сообщениях трассировки.
...
def bar(arg1):
try:
foo()
except Exception as e:
import sys
raise type(e)(str(e) +
' happens at %s' % arg1).with_traceback(sys.exc_info()[2])
bar('arg1')
Обновление 3
Комментатор спросил, есть ли способ , который будет работать как в Python 2 и 3. Несмотря на то, что ответ может показаться, что «Нет» из - за различия синтаксиса, то есть способ обойти это, используя вспомогательную функцию как reraise()
в six
Add- на модуле. Итак, если вы по какой-то причине не хотите использовать библиотеку, ниже представлена упрощенная автономная версия.
Также обратите внимание на то, что, поскольку исключение повторно возникает внутри reraise()
функции, оно будет появляться при любом возбуждении трассировки, но конечный результат - это то, что вы хотите.
import sys
if sys.version_info.major < 3:
exec("""def reraise(exc_type, exc_value, exc_traceback=None):
raise exc_type, exc_value, exc_traceback""")
else:
def reraise(exc_type, exc_value, exc_traceback=None):
if exc_value is None:
exc_value = exc_type()
if exc_value.__traceback__ is not exc_traceback:
raise exc_value.with_traceback(exc_traceback)
raise exc_value
def foo():
try:
raise IOError('Stuff')
except:
raise
def bar(arg1):
try:
foo()
except Exception as e:
reraise(type(e), type(e)(str(e) +
' happens at %s' % arg1), sys.exc_info()[2])
bar('arg1')
message
атрибута Exception я обнаружил этот вопрос SO, BaseException.message устарел в Python 2.6 , что, похоже, указывает на то, что его использование теперь не рекомендуется (и почему его нет в документации).