在以下代码中引发第二个(A
)时,我的第一个异常(B
)会发生什么?
class A(Exception): pass
class B(Exception): pass
try:
try:
raise A('first')
finally:
raise B('second')
except X as c:
print(c)
如果使用X = A
运行,我会:
Traceback (most recent call last): File "raising_more_exceptions.py", line 6, in raise A('first') __main__.A: first During handling of the above exception, another exception occurred: Traceback (most recent call last): File "raising_more_exceptions.py", line 8, in raise B('second') __main__.B: second
但如果X = B
我得到:
second
这个问题专门针对Python 3,因为它的异常处理与Python 2完全不同。
答案 0 :(得分:13)
回答问题3,你可以使用:
QueryParser
将删除异常raise B('second') from None
追溯。
A
答案 1 :(得分:9)
'cause'异常在上一个异常处理程序中以c .__ context__的形式提供。 Python正在使用此信息来呈现更有用的回溯。在Python 2.x下,原始异常将丢失,这仅适用于Python 3。
通常你会使用它来抛出一致的异常,同时仍然保持原始异常可访问(尽管从异常处理程序自动发生它非常酷,我不知道!):
try:
do_something_involving_http()
except (URLError, socket.timeout) as ex:
raise MyError('Network error') from ex
更多信息(以及其他一些非常有用的功能):http://docs.python.org/3.3/library/exceptions.html
答案 2 :(得分:8)
Pythons异常处理一次只处理一个异常。但是,异常对象与其他所有对象一样受到相同的变量规则和垃圾收集的约束。因此,如果将异常对象保存在某个变量的某个地方,以后可以处理它,即使引发了另一个异常。
在您的情况下,当在“finally”语句中引发异常时,Python 3将在第二个异常之前打印出第一个异常的回溯,以便更有帮助。
更常见的情况是您希望在显式异常处理期间引发异常。然后,您可以在下一个异常中“保存”异常。只需将其作为参数传递:
>>> class A(Exception):
... pass
...
>>> class B(Exception):
... pass
...
>>> try:
... try:
... raise A('first')
... except A as e:
... raise B('second', e)
... except Exception as c:
... print(c.args[1])
...
first
如您所见,您现在可以访问原始例外。
答案 3 :(得分:7)
我相信回答你问题的所有要素都已经存在于现有的答案中。让我结合并详细说明。
让我重复一下您的问题代码,以提供行号参考:
1 class A(Exception): pass
2 class B(Exception): pass
3
4 try:
5 try:
6 raise A('first')
7 finally:
8 raise B('second')
9 except X as c:
10 print(c)
所以回答你的问题:
第6行引发了您的第一个异常A
。第{7}行中的finally
子句始终执行try
块(第5行) -6)是留下的,无论是因为成功完成还是因为引发异常而离开了。
在执行finally
子句时,第8行引发了另一个异常B
。正如Lennart和Ignazio指出的那样,只有一个例外,即最近被提出的例外,可以被追踪。因此,只要引发B
,就会退出整个try
块(第4-8行),并且第9行中的B
语句会捕获异常except
如果匹配(如果X
是B
)。
希望现在从我对1的解释中可以清楚地看到这一点。但是你可以捕捉到内/下/第一个异常。要合并Lennart的答案,稍作修改,以下是如何捕捉两者:
class A(Exception): pass
class B(Exception): pass
try:
try:
raise A('first')
except A as e:
raise B('second', e)
except Exception as c:
print(c)
输出结果为:
('second', A('first',))
在Lennart的例子中,这个问题的解决方案是行except A as e
,其中内部/下部/第一个异常被捕获并存储在变量e
中。
作为对何时捕捉异常,何时忽略它们以及何时重新加注的一般直觉,可能this question and Alex Martelli's answer帮助。
答案 4 :(得分:6)