Я бы сделал это так, поэтому для изменения его типа в 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 2012-05-16 (мое первое обновление было опубликовано в 2012-03-12).Поэтому в настоящее время в Python 3.5.2 в любом случае вам нужно что-то делать в этом направлении, чтобы сохранить трассировку, а не жестко кодировать тип исключения в функции bar()
.Также обратите внимание, что в отображаемых сообщениях трассировки будет строка:
During handling of the above exception, another exception occurred:
.
# for Python 3.x
...
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
.Поэтому, если вы по какой-то причине не хотите использовать библиотеку, ниже приведена упрощенная автономная версия.
Обратите внимание, что, поскольку исключение вызывается в функции reraise()
, оно будет отображаться при любой трассировке.поднят, но конечный результат - то, что вы хотите.
import sys
if sys.version_info.major < 3: # Python 2?
# Using exec avoids a SyntaxError in Python 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')