重新抛出Python异常。抓哪个?

问题描述 投票:0回答:3

我正在学习使用Python。我刚刚看到这篇文章: http://nedbatchelder.com/blog/200711/rethroing_exceptions_in_python.html 它描述了Python中重新抛出异常,如下所示:

try:
    do_something_dangerous()
except:
    do_something_to_apologize()
    raise

既然重新抛出异常,就应该有一个“外部catch-except”语句。但现在,我在想,如果 except 内的

do_something_to_apologize()
抛出错误怎么办?哪一个会被外面的“catch- except”捕获呢?是你重新扔的还是
do_something_to_apologize()
扔的? 或者优先级最高的异常会首先被捕获吗?

python exception throw rethrow
3个回答
94
投票

尝试看看:

def failure():
    raise ValueError, "Real error"

def apologize():
    raise TypeError, "Apology error"

try:
    failure()
except ValueError:
    apologize()
    raise

结果:

Traceback (most recent call last):
  File "<pyshell#14>", line 10, in <module>
    apologize()
  File "<pyshell#14>", line 5, in apologize
    raise TypeError, "Apology error"
TypeError: Apology error

原因:原始函数的“真正”错误已经被

except
捕获。 在达到
apologize
之前,raise
 引发新错误
。 因此,
raise
子句中的
except
永远不会执行,只有道歉的错误向上传播。  如果 
apologize
 引发错误,Python 无法知道您将在 
apologize
 之后引发不同的异常。

请注意,在 Python 3 中,回溯将提及

both 异常,并有一条消息解释第二个异常是如何出现的:

Traceback (most recent call last): File "./prog.py", line 9, in <module> File "./prog.py", line 2, in failure ValueError: Real error During handling of the above exception, another exception occurred: Traceback (most recent call last): File "./prog.py", line 11, in <module> File "./prog.py", line 5, in apologize TypeError: Apology error

但是,第二个异常(“道歉”异常)仍然是唯一向外传播的异常,并且可以被更高级别的

except

 子句捕获。  原始异常在回溯中提到,但被包含在后面的异常中并且无法再捕获。


8
投票
do_something_to_apologize() 抛出的异常将被捕获。由于 do_something_to_apologize 抛出异常,包含 raise 的行永远不会运行。另外,我不相信 python 异常中有任何“优先级”的概念。


7
投票
我相信更好的想法是使用

raise NewException("Explain why") from CatchedException
图案。特别是,考虑到 Python 3 和 @BrenBarn 给出的示例,我使用以下

def failure(): raise ValueError("Real error") try: failure() except ValueError as ex: raise TypeError("Apology error") from ex
产生

--------- ValueError---- Traceback (most recent call last) 4 try: ----> 5 failure() 6 except ValueError as ex: 1 def failure(): ----> 2 raise ValueError("Real error") 3 ValueError: Real error The above exception was the direct cause of the following exception: -----TypeError----- Traceback (most recent call last) 5 failure() 6 except ValueError as ex: ----> 7 raise TypeError("Apology error") from ex TypeError: Apology error
您还可以通过从 None 引发新异常来抑制原始异常上下文。代码将更改为

def failure(): raise ValueError("Real error") try: failure() except ValueError as ex: raise TypeError("Apology error") from None
..它产生以下输出

--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In[2], line 7 5 failure() 6 except ValueError as ex: ----> 7 raise TypeError("Apology error") from None TypeError: Apology error
    
© www.soinside.com 2019 - 2024. All rights reserved.