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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25001971/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 19:32:21  来源:igfitidea点击:

rethrowing python exception. Which to catch?

pythonexceptionthrowrethrow

提问by Bosiwow

I'm learning to use python. I just came across this article: http://nedbatchelder.com/blog/200711/rethrowing_exceptions_in_python.htmlIt describes rethrowing exceptions in python, like this:

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

try:
    do_something_dangerous()
except:
    do_something_to_apologize()
    raise

Since you re-throw the exception, there shouold be an "outer catch-except" statement. But now, I was thinking. What if the do_something_to_apologize() inside the except throws an error. Which one will be caught in the outer "catch-except"? The one you rethrow or the one thrown by do_something_to_apologize() ? Or will the exception with the highest priotiry be caught first?

由于您重新抛出异常,因此应该有一个“外部 catch-except”语句。但现在,我在想。如果 except 中的 do_something_to_apologize() 抛出错误怎么办。哪个会被外层的“catch-except”捕获?你重新抛出的那个还是 do_something_to_apologize() 抛出的那个?还是优先级最高的异常会先被捕获?

采纳答案by BrenBarn

Try it and see:

试试看:

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

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

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

The result:

结果:

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

The reason: the "real" error from the original function was already caught by the except. apologizeraises a new error before the raiseis reached. Therefore, the raisein the exceptclause is never executed, and only the apology's error propagates upward. If apologizeraises an error, Python has no way of knowing that you were going to raise a different exception after apologize.

原因:来自原始函数的“真实”错误已经被except. 达到之前apologize引发新错误。因此,从不执行in子句,只有道歉的错误向上传播。如果引发错误,Python 无法知道您将在.raiseraiseexceptapologizeapologize

Note that in Python 3, the traceback will mention bothexceptions, with a message explaining how the second one arose:

请注意,在 Python 3 中,回溯将提及这两个异常,并带有一条消息解释第二个异常是如何出现的:

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

However, the second exception (the "apology" exception) is still the only one that propagates outward and can be caught by a higher-level exceptclause. The original exception is mentioned in the traceback but is subsumed in the later one and can no longer be caught.

但是,第二个异常(“道歉”异常)仍然是唯一一个向外传播并且可以被更高级别的except子句捕获的异常。回溯中提到了原始异常,但包含在后面的异常中,无法再捕获。

回答by ibebrett

The exception thrown by do_something_to_apologize() will be caught. The line containing raise will never run, because of the exception thrown by do_something_to_apologize. Also, I don't believe there is any idea of "priority" in python exceptions.

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