The exception is raised. The finally
block is executed when the generator is closed. Closing a generator is done by raising a GeneratorExit
exception in the generator context.
The exception in ignored because the generator isn't closed until it is being deleted (automatically in this case, when Python exits); the generator __del__
handler closes the generator, which triggers the 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
Exceptions raised during cleanup are always ignored; see the 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.
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:
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; see the 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.