【问题标题】:Exceptions vs Errors in PythonPython 中的异常与错误
【发布时间】:2020-06-27 17:33:52
【问题描述】:

我来自 Java,其中异常和错误是完全不同的东西,它们都源自名为 Throwable 的东西。 在 Java 中,您通常不应该尝试捕获错误。

在 Python 中,虽然区别似乎很模糊。

到目前为止,在阅读了一些文档并检查了 the hierarchy 之后,我有以下问题:

  1. 语法错误当然会导致您的程序根本无法启动。正确的?

  2. “在执行过程中检测到的错误称为异常,并不是无条件致命的”(根据the tutorial)。这里的“致命”是什么意思?此外,一些像 AttributeError 这样的对象(根据上面的定义)实际上是异常,即使它们的名称中包含 Error,这个结论是否正确?

  3. 某些类派生自 Exception 但名称中包含 Error。这不是很混乱吗?但即便如此,这意味着名称中的 Error 并没有什么特别之处,它仍然是一个 Exception。或不... ?

  4. “所有内置的、非系统退出的异常都源自 [Exception]”(引用自 here
    那么哪些是系统退出异常,哪些不是?目前还不清楚。所有用户定义的异常也应该从 Exception 派生。所以基本上作为一个初学者,除了异常,我还需要担心其他什么吗?好像没有。

  5. 警告也来自异常。那么警告是致命的还是系统退出的,还是都没有?

  6. AssertionError 适合所有这些吗?它是致命的还是系统退出?

  7. 如何知道或指定某个异常类代表致命或系统退出异常?

【问题讨论】:

  • 正确,为了您的目的,只有例外。
  • 不确定这些东西在 Java 中有何不同,但在 PHP 中,“错误”基本上只是在屏幕/日志中产生错误消息,而异常是可以通过 @ 分层处理的东西987654325@。从这个意义上说,Python 没有做出这种区分。每个可能的错误都是异常,可以通过try..except处理。

标签: python exception


【解决方案1】:
  1. 是的。 SyntaxError 无法捕获,除非是动态执行的代码(通过 eval/exec),因为它发生在代码实际运行之前。
  2. “致命”的意思是“不管代码怎么说,程序都会死掉”; Python 中的异常不会发生这种情况,它们都是可捕获的。 os._exit 可以强行杀死进程,但它是通过绕过异常机制来实现的。
  3. 异常和错误之间没有区别,因此命名无关紧要。
  4. 系统退出异常源自BaseException,但不是Exception。但它们可以像任何其他异常一样被捕获
  5. 警告的行为因警告过滤器而异,从 Exception 派生意味着它们不在“系统退出”类别中
  6. AssertionError 只是另一个 Exception 子类,所以它不是“系统退出”。它只是与 assert 语句相关联,该语句具有特殊语义。
  7. 源自BaseException 但不是Exception(例如SystemExitKeyboardInterrupt)的东西是“不合理的捕捉”(或者如果你确实捕捉它们,它应该几乎总是记录/执行清理和重新抛出它们),其他所有东西(也来自Exception)是“有条件地合理捕捉”。没有其他区别。

明确地说,“系统退出”只是一种表达“except Exception: 无法捕获的东西”的方式;如果不涉及 except 块,则所有异常(除了警告,如前所述,根据警告过滤器的行为不同)都是“系统退出”。

【讨论】:

  • 你的答案非常好(本页最好的),我已经重读了很多遍。而且……这整个事情看起来一团糟(与其他语言的情况相比)。混乱的等级制度,混乱的术语。我想这都是出于历史原因。甚至没有基础Error 类。然后是一些从异常派生的称为错误的东西。只是很奇怪。我知道你对此无能为力,我将这里的评论留给其他新手(Python)。
  • @peter.petrov:我认为要记住的主要事情是“错误”没有单独的类别。 “错误”和“异常”在 Python 中是同义词。除此之外,只需查看exception hierarchy,您就知道哪些类派生自BaseException,而不是派生自Exception,并记住永远不要使用裸except:(这也会捕获BaseException 的东西)。
  • 我同意层次结构有点偏离; MemoryError 不应该落入Exception 之下(在极少数情况下你想抓住它,但即使你这样做了,你也应该专门抓住它,与KeyboardInterrupt 相同,而不是与@987654347 意外抓住它@ 这可能不是为了处理内存不足的情况而编写的)。同样,OverflowError,用于超出表示限制的算术,实际上主要用于“传递的 Python int 太大而无法转换为 C 寄存器宽度类型”;它根本不是ArithmeticError(父类)。
  • 但是其余的大部分都是有道理的。它可能不同意从语言中区分不可捕获的终端错误和可捕获的运行时异常的更严格的命名法,但这是因为 Python 确保没有任何东西(除了故意的 os._exit 调用或导致解释器段错误的错误)是终端的(“我们是这里的所有成年人”的意思是如果你真的想抓到不该抓的东西,他们会让你抓到的)。 Python 更简单,最终会让那些期望/习惯于更复杂的人感到困惑。
【解决方案2】:

异常是为程序员设计的,让他们知道如何处理它们,例如 outOfRange 一旦出现异常,程序员必须决定如何处理它,代码才能继续相对流畅地运行

另一方面,错误表示程序员无法预见为导入错误或内存错误的问题 仍然可以解决错误并确保软件继续运行,但显然并非一切都能够继续顺利运行。

【讨论】:

    猜你喜欢
    • 2013-06-23
    • 1970-01-01
    • 1970-01-01
    • 2010-10-24
    • 2010-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多