python - 在 python 增强生成器中避免 "exception ignored"

标签 python exception generator coroutine

我在 python 中有一个协程(增强型生成器),其中有一些代码要在数据结束后执行:

def mycoroutine():
  try:
    while True:
      data = (yield)
      print data
  finally:
    raise ValueError
    print "END"

co = mycoroutine()
co.next()

for i in (1,2,3):
  co.send(i)

未引发 ValueError 异常,但解释器只是打印:

Exception ValueError: ValueError() in <generator object mycoroutine at 0x2b59dfa23d20> ignored

有没有办法在调用者中捕获异常?

最佳答案

引发了异常finally block 在生成器关闭时执行。关闭生成器是通过调用 GeneratorExit exception 来完成的。在生成器上下文中。

异常被忽略,因为生成器在被删除之前不会关闭(在这种情况下,当 Python 退出时自动关闭);生成器 __del__ 处理程序关闭生成器,这会触发 finally: block :

>>> def mycoroutine():
...   try:
...     while True:
...       data = (yield)
...       print data
...   finally:
...     raise ValueError
...     print "END"
... 
>>> co = mycoroutine()
>>> co.next()
>>> co.close()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 7, in mycoroutine
ValueError
>>> co = mycoroutine()
>>> co.next()
>>> del co
Exception ValueError: ValueError() in <generator object mycoroutine at 0x1046a9fa0> ignored

清理期间引发的异常总是被忽略;查看object.__del__() documentation :

Warning: Due to the precarious circumstances under which __del__() methods are invoked, exceptions that occur during their execution are ignored, and a warning is printed to sys.stderr instead.

解决方案是在清理生成器时不引发异常,或者通过显式关闭生成器来捕获异常:

>>> co = mycoroutine()
>>> co.next()
>>> try:
...     co.close()
... except ValueError:
...     pass
... 
>>> del co
>>> # No exception was raised
... 

您还可以捕获 GeneratorExit 异常并在此时执行一些清理:

def mycoroutine():
  try:
    while True:
      data = (yield)
      print data
  except GeneratorExit:
    print "Generator exiting!"

但请注意,除了 StopIterationGeneratorExit 之外的任何异常都将始终被传播;查看generator.close() documentation :

If the generator function then raises StopIteration (by exiting normally, or due to already being closed) or GeneratorExit (by not catching the exception), close returns to its caller. If the generator yields a value, a RuntimeError is raised. If the generator raises any other exception, it is propagated to the caller.

关于python - 在 python 增强生成器中避免 "exception ignored",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18637048/

相关文章:

c# - 避免在 EF 中插入时发生键冲突

Python 生成器函数和排列

python - 如何从生成器构建 numpy 数组?

Python:迭代具有不同维数的列表,有通用的方法吗?

python - 用python读取一个简单的.txt文件,为什么这段简单的代码会输出每一行? python 如何知道它应该这样做?

python - Google App Engine Python simplejson 转义?

python - 在pyqt中显示相机

java - 修改ArrayList的ArrayList时并发修改异常

java - 如何在 boolean 方法中抛出三个异常?

javascript - 图像文件到可汗学院代码