2009-12-11 102 views
8

我正在构建一个工具,在异常向上传播时,有关异常上下文的新数据将被添加到异常中。问题是,在异常到达顶层时,所有额外的上下文数据都在那里,但只显示最新的堆栈跟踪。是否有一种简单的方法可以让异常显示原始堆栈跟踪而不是最后一个堆栈跟踪,或者我应该像第一次抓取原始堆栈跟踪那样异常传播?Python异常传播

例如,下面的代码:

def a(): 
    return UNBOUND 
def b(): 
    try: 
     a() 
    except Exception as e: 
     raise e 
b() 

产生以下异常:

Traceback (most recent call last): 
    File "test.py", line 8, in <module> 
    b() 
    File "test.py", line 7, in b 
    raise e 
NameError: global name 'UNBOUND' is not defined 

其中,理想情况下,我想以某种方式显示给用户这样的:

Traceback (most recent call last): 
    File "test.py", line 8, in <module> 
    File "test.py", line 2, in a 
    return UNBOUND 
NameError: global name 'UNBOUND' is not defined 

因为这将用户指向最初发生错误的行。

回答

26

Python异常有点像java,有一种方法可以在不截断堆栈的情况下重新抛出异常。

仅仅使用raise而没有参数。其结果是:

Traceback (most recent call last): 
    File "./exc.py", line 11, in <module> 
    b() 
    File "./exc.py", line 7, in b 
    a() 
    File "./exc.py", line 4, in a 
    return UNBOUND 
NameError: global name 'UNBOUND' is not defined 

可以修改一些东西有关e对象,即使你只是raise没有这样的说法 - 例如:

e.args = ("hi!",) 
raise 

将真正改变异常消息。您也可以通过这种方式更改其他选项 - 而不会破坏堆栈。