【问题标题】:rethrowing python exception. Which to catch?重新抛出 python 异常。抓哪个?
【发布时间】:2014-09-20 00:54:20
【问题描述】:

我正在学习使用 python。我刚看到这篇文章: http://nedbatchelder.com/blog/200711/rethrowing_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() 扔的那个? 还是先捕获优先级最高的异常?

【问题讨论】:

  • 先发生的那个。
  • 你抓到的那个?
  • 这正是为什么 (a) 你想要编写不能引发的异常处理程序,或者只能在你非常了解的特定情况下引发,以及 (b) 你想要实际得到异常对象,至少在早期调试期间,所以你可以,例如,print('do_something_dangerous raised {!r}'.format(e)) 至少水平,看看发生了什么。
  • 另外,请注意,在 Ned 的“真实”代码中,他只处理 except Exception,而不仅仅是裸露的 except:。这部分是为了让他用except Exception, e: 捕获异常(虽然这是一个旧博客,所以它使用旧语法;你想要except Exception as e:),部分是为了避免捕获像KeyboardInterrupt 这样的东西,你很少想处理。 (当你这样做时,用except BaseException: 明确表示。这在旧版 Python 中不是一个选项,但假设你正在编写,例如,2.6 或 3.0,它是。)
  • @user2815780:在这种情况下,您可能希望以某种方式处理apologize 代码,因此您可以引发异常,让您编码/最终用户知道您失败然后失败清理。 (或者也许在目标驱动器/文件系统上的临时位置创建文件夹,这样最坏的情况就不会那么糟糕,也许不必报告。)但除此之外,是的,这是对异常的完全合理的使用- 处理可能引发的代码。

标签: python exception throw rethrow


【解决方案1】:

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

【讨论】:

  • 似乎另一个答案获得了最多的选票,可能是由于它的细节和“试试看”的方法(总是好的),但恕我直言,它实际上并没有回答原来的问题,即“哪个" ibebrett 的这个回答确实回答了这个问题。一般规则是,一旦某个东西引发了异常,在第一个异常被捕获之前,其他任何东西都不能引发异常:因此,如果道歉() 引发异常,那么它之后的引发将永远不会被执行。
【解决方案2】:

试试看:

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 之前引发一个新错误。因此,except 子句中的raise 永远不会被执行,只有道歉的错误会向上传播。如果apologize 引发错误,Python 无法知道您将在apologize 之后引发不同的异常。

请注意,在 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

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

【讨论】:

  • 有没有办法在 python 2 中获得 python 3 的行为?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-10
  • 1970-01-01
  • 1970-01-01
  • 2012-06-29
  • 1970-01-01
  • 2010-10-03
相关资源
最近更新 更多