我查看了内置python异常的层次结构,并注意到StopIterationGeneratorExit具有不同的基类:

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



https://docs.python.org/2/library/exceptions.html#exceptions.StopIteration



这对我来说不是很清楚。从它们不通知错误的意义上来说,两者是相似的,而是改变代码流的“事件”。因此,从技术上讲它们不是错误,并且我知道应该将它们与其余的异常分开……但是为什么一个是BaseException的子类,而另一个是Exception的子类呢?

通常,我一直认为Exception子类是错误,并且当我编写盲目try: except:(例如,调用第三方代码)时,我总是 try catch Exception,但是也许那是错误的,我应该捕获StandardError

最佳答案

通常使用try:...,但Exception:...块除外。

如果GeneratorExit将从Exception继承,则会出现以下问题:

def get_next_element(alist):
    for element in alist:
        try:
            yield element
        except BaseException:  # except Exception
            pass

for element in get_next_element([0,1,2,3,4,5,6,7,8,9]):
    if element == 3:
        break
    else:
        print(element)

0
1
2
Exception ignored in: <generator object get_next_element at 0x7fffed7e8360>
RuntimeError: generator ignored GeneratorExit

这个例子很简单,但是想像一下try块中一个更复杂的操作,如果失败,它将简单地忽略问题(或打印一条消息)并进入下一个迭代。

如果捕获到通用的Exception,最终将阻止生成器的用户中断循环而没有得到RuntimeError。

更好的解释是here

编辑:在这里回答,因为评论太久了。

我宁愿相反。 GeneratorExit应该继承自Exception而不是BaseException。当您捕获Exception时,您基本上想捕获几乎所有内容。 BaseExceptionPEP-352所述,用于需要“异常(exception)”的那些异常(exception),以便允许用户从否则会捕获它们的代码中逃脱。这样,您可以,例如,仍然CTRL-C运行代码。 GeneratorExit属于该类别,以便打破循环。在comp.lang.python上有趣的对话。

10-06 04:57