【发布时间】:2015-07-14 12:31:21
【问题描述】:
我正在查看内置 python 异常的层次结构,我注意到 StopIteration 和 GeneratorExit 具有不同的基类:
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StandardError
+-- Warning
或者在代码中:
>>> GeneratorExit.__bases__
(<type 'exceptions.BaseException'>,)
>>> StopIteration.__bases__
(<type 'exceptions.Exception'>,)
当我转到每个异常的具体描述时,我可以阅读以下内容:
https://docs.python.org/2/library/exceptions.html#exceptions.GeneratorExit
异常生成器退出
在调用生成器的 close() 方法时引发。它直接继承自 BaseException 而不是 StandardError,因为它在技术上不是错误。
https://docs.python.org/2/library/exceptions.html#exceptions.StopIteration
异常停止迭代
由迭代器的 next() 方法引发,表示没有其他值。这是从 Exception 而不是 StandardError 派生的,因为这在其正常应用程序中不被视为错误。
这对我来说不是很清楚。两者在某种意义上是相似的,它们不通知错误,而是更改代码流的“事件”。所以,从技术上讲,它们不是错误,我知道它们应该与其他异常分开......但为什么一个是BaseException 的子类而另一个是Exception 的子类?。
一般来说,我一直认为Exception 子类是错误的,当我写一个盲目的try: except:(例如调用第三方代码)时,我总是试图捕捉Exception,但也许那是错误的,我应该会赶上StandardError。
【问题讨论】:
-
我怀疑这是出于历史原因:StopIteration & Exception 早在 BaseException 之前就已经存在,更改它可能会无缘无故地破坏一些旧代码。请参阅PEP 352 异常所需的超类。请注意,StopIteration 仍然派生自 Exception in Python 3,即使这与现代模式不一致。 (我把它放在评论而不是答案中,因为这是猜测)。
-
@PM2Ring 这听起来很合乎逻辑。虽然......如果python 3仍然将
StopIteration定义为Exception的子类,这可能有一个隐藏的原因 -
相关 Python 错误跟踪链接 Issue1537:将 GeneratorExit 的基类从 Exception 更改为 BaseException
标签: python exception exception-handling python-internals