简体   繁体   English

避免在python增强型生成器中“忽略异常”

[英]Avoid “exception ignored” in python enhanced generator

I have a coroutine (Enhanced generators) in python with some code to be executed after the end of data: 我在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)

The ValueError exception is not raised but the interpreter simply prints: 不会引发ValueError异常,但解释器只会打印:

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

Is there a way to catch the exception in the caller? 有没有办法在调用者中捕获异常?

The exception is raised. 异常 The finally block is executed when the generator is closed. 当发电机关闭时执行finally块。 Closing a generator is done by raising a GeneratorExit exception in the generator context. 关闭生成器是通过在生成器上下文中引发GeneratorExit异常来完成的。

The exception in ignored because the generator isn't closed until it is being deleted (automatically in this case, when Python exits); 忽略异常,因为生成器在被删除之前不会被关闭(在这种情况下,当Python退出时自动生成); the generator __del__ handler closes the generator, which triggers the finally: block: 生成器__del__处理程序关闭生成器,触发finally:块:

>>> 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

Exceptions raised during cleanup are always ignored; 清理过程中出现的异常总是被忽略; see the object.__del__() documentation : 看到object.__del__()文档

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. 警告 :由于调用__del__()方法的不稳定情况,将忽略执行期间发生的异常,并向sys.stderr警告。

The solution is to not have exceptions being raised when a generator is cleaned up, or catch the exception by closing the generator explicitly: 解决方案是在清理生成器时不会引发异常,或通过显式关闭生成器来捕获异常:

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

You could also catch the GeneratorExit exception and perform some cleanup at that point: 您还可以捕获GeneratorExit异常并在此时执行一些清理:

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

but note that any exception other than StopIteration or GeneratorExit will always be propagated; 但请注意,除了StopIterationGeneratorExit之外的任何异常都将被传播; see the generator.close() documentation : 请参阅generator.close()文档

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. 如果生成器函数然后引发StopIteration (通过正常退出,或者由于已经关闭)或GeneratorExit (通过不捕获异常),则关闭返回其调用者。 If the generator yields a value, a RuntimeError is raised. 如果生成器产生一个值,则引发RuntimeError If the generator raises any other exception, it is propagated to the caller. 如果生成器引发任何其他异常,它将传播给调用者。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM