我想实现以下目标:
def foo(): try: raise IOError('Stuff ') except: raise def bar(arg1): try: foo() except Exception as e: e.message = e.message + 'happens at %s' % arg1 raise bar('arg1') Traceback... IOError('Stuff Happens at arg1')
但是我得到的是:
Traceback.. IOError('Stuff')
关于如何实现这一目标的任何线索?如何在Python 2和3中做到这一点?
我会这样做,因此更改它的类型foo()将不需要也将其更改bar()。
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,我的第一次更新中的代码在语法上是不正确的,并且在message2012BaseException年5月16日对PEP 352的更改中撤消了启用属性的想法(我的第一次更新发布于2012-03-12) 。因此,当前,无论如何,在Python 3.5.2中,您都需要按照以下步骤进行操作以保留回溯,而不是硬编码function中的异常类型bar()。另请注意,将出现以下行:
message
BaseException
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()
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')