没有参数的raise语句的documentation表示
如果没有表达式,则raise重新引发当前作用域中活动的最后一个异常。
我曾经认为这意味着当前函数必须执行except
子句。在阅读this question并尝试一点之后,我认为这意味着堆栈上的任何函数都必须执行except
子句,但我不确定。另外,我已经意识到我不知道堆栈跟踪如何使用no-arg raise:
def f():
try:
raise Exception
except:
g()
def g():
raise
f()
产生
Traceback (most recent call last):
File "foo", line 10, in <module>
f()
File "foo", line 5, in f
g()
File "foo", line 3, in f
raise Exception
Exception
这看起来不像初始加注时的堆栈,或者重新加注时的堆栈,或者两个堆栈的串联,或者我能理解的任何东西。
我是否正确地寻找执行except
子句的堆栈上的任何函数?此外,堆栈跟踪如何在重新加载时起作用?
答案 0 :(得分:15)
当你raise
没有参数时,解释器会查找最后异常引发并处理。然后它就像使用raise
一样使用最新的异常类型,值和回溯。
它存储在当前线程的解释器状态中,可以使用sys.exc_info()
检索相同的信息。通过'处理'我的意思是一个except子句捕获了异常。引用try
statement documentation:
在执行except子句的套件之前,有关异常的详细信息被分配给
sys
模块中的三个变量:sys.exc_type
接收标识异常的对象;sys.exc_value
收到异常的参数;sys.exc_traceback
收到一个回溯对象(请参阅The standard type hierarchy标识程序中发生异常的点。这些详细信息也可以通过sys.exc_info()
函数获得,该函数返回一个元组{{1} }。
请参阅Python评估循环中的implemenation notes(C代码),具体来说:
第二个 bullet是为了向后兼容:它是(并且是)常见的 具有在捕获异常时调用的函数,以及 让该函数通过sys.exc_ZZZ访问捕获的异常。 (例如:traceback.print_exc())。
追溯反映了您如何准确地进行重新加注。它是当前堆栈(第10行调用(exc_type, exc_value, exc_traceback)
,第5行调用f()
)加上引发的异常的原始位置:第3行。
答案 1 :(得分:2)
事实证明,Python使用了一种令人惊讶的方式来建立追溯。除了在异常创建时(like Java)或引发异常时(就像我以前认为的那样)构建整个堆栈跟踪,Python会在异常冒泡时一次建立一帧局部回溯。>
Every time an exception bubbles up to a new stack frame, as well as when an exception is raised with the one-argument form of raise
(或Python 2上的两个参数的形式),Python字节码解释器循环执行PyTraceback_Here
,将新的头添加到表示堆栈跟踪的跟踪对象的链接列表中。 (在Python 2上,0参数<android.support.v7.widget.Toolbar
...
app:titleTextAppearance="@style/Toolbar.TitleText"/>
和3参数raise
跳过此步骤。)
Python维护了每个线程的异常(和回溯)堆栈,这些异常(和回溯)由尚未完成执行的raise
和except
块挂起。 0参数finally
restores,即使raise
或except
在不同的函数中,也由堆栈顶部的条目表示的异常(和回溯)。>
finally
执行其f
时:
raise
Python建立与该行相对应的回溯:
raise Exception
当 File "foo", line 3, in f
raise Exception
执行0参数g
时,将还原此追溯,但不会为0参数raise
行添加任何条目。
此后,随着异常在整个堆栈的其余部分冒出,将raise
和g()
调用的条目添加到堆栈跟踪中,从而显示最终的堆栈跟踪: / p>
f()
答案 2 :(得分:-1)
以下代码可能有助于您了解 raise 关键字的工作原理:
def fun(n):
try:
return 0 / n
except:
print('an exception raised:')
raise
try:
fun(0)
except:
print('cannot divide by zero')
try:
fun('0')
except:
print('cannot divide by a string')