Я б це зробив так, щоб змінити його тип 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()в sixAdd- на модулі. Отже, якщо ви хочете скористатися бібліотекою з якихось причин, нижче - спрощена окрема версія.
Зауважте також, що оскільки виняток повторно збільшується в межах 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')
messageатрибуту «Виняток», я знайшов це питання ТА , BaseException.message застарілий у Python 2.6 , який, схоже, вказує на його використання зараз не рекомендується (і чому його немає в документах).