bgu*_*ach 6 python exception-handling exception python-internals
我正在看内置Python异常的层次,我注意到StopIteration并GeneratorExit有不同的基类:
BaseException
+-- SystemExit
+-- KeyboardInterrupt
+-- GeneratorExit
+-- Exception
+-- StopIteration
+-- StandardError
+-- Warning
Run Code Online (Sandbox Code Playgroud)
或者在代码中:
>>> GeneratorExit.__bases__
(<type 'exceptions.BaseException'>,)
>>> StopIteration.__bases__
(<type 'exceptions.Exception'>,)
Run Code Online (Sandbox Code Playgroud)
当我转到每个例外的具体描述时,我可以阅读以下内容:
https://docs.python.org/2/library/exceptions.html#exceptions.GeneratorExit
例外GeneratorExit
调用生成器的close()方法时引发.它直接继承自BaseException而不是StandardError,因为它在技术上不是错误.
https://docs.python.org/2/library/exceptions.html#exceptions.StopIteration
例外StopIteration
由迭代器的next()方法引发,表示没有其他值.这是从Exception而不是StandardError派生的,因为这在其正常应用程序中不被视为错误.
这对我来说不是很清楚.两者在它们不通知错误的意义上是相似的,而是用于改变代码流的"事件".因此,它们在技术上不是错误,我理解它们应该与其余的异常分开......但为什么一个是子类,BaseException另一个是Exception?的子类.
一般来说,我一直认为Exception子类是错误的,当我写盲人try: except:(例如调用第三方代码)时,我总是试图捕捉Exception,但也许这是错误的,我应该抓住StandardError.
使用try:...除了Exception:... blocks之外是很常见的.
如果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
Run Code Online (Sandbox Code Playgroud)
这个例子非常简单,但是在try块中想象一个更复杂的操作,如果失败,它将简单地忽略问题(或打印消息)并进入下一次迭代.
如果您将捕获通用异常,则最终会阻止生成器的用户在不获取RuntimeError的情况下中断循环.
这里有一个更好的解释.
编辑:在这里回答,因为评论太长了.
我宁愿说相反的话.GeneratorExit应该继承Exception而不是BaseException.当你抓到Exception你基本上想要抓住几乎所有东西.BaseException正如PEP-352所述,是针对那些需要"例外"的例外,以便允许用户逃避原本会捕获它们的代码.例如,您可以使用CTRL-C运行代码.GeneratorExit落入该类别以打破循环.关于comp.lang.python的一个有趣的对话.
| 归档时间: |
|
| 查看次数: |
1082 次 |
| 最近记录: |