我会这样做,因此在 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,我第一次更新中的代码在语法上不正确,加上 BaseException 上具有 message 属性的想法是 2012 年 5 月 16 日的 retracted in a change to PEP 352(我的第一次更新发布于 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 中使用。虽然由于语法差异,答案可能看起来是“否”,但有一种解决方法通过在 six 附加模块中使用像 reraise() 这样的辅助函数。因此,如果您出于某种原因不想使用该库,下面是一个简化的独立版本。
还要注意,由于在 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')