[Python-ideas] Yield-From: Finalization guarantees

Nick Coghlan ncoghlan at gmail.com
Sun Mar 29 01:56:44 CET 2009


Greg Ewing wrote:
> Nick Coghlan wrote:
> 
>> Generators that catch and do anything with GeneratorExit other than turn
>> it into StopIteration are almost always going to be broken - the new
>> expression needs to avoid making it easy to do that accidentally.
> 
> However, as this example shows, the suggested solution
> of reraising GeneratorExit is not viable because it
> violates the inlining principle.
> 
> The basic problem is that there's no way of telling the
> difference between a StopIteration that means "it's okay,
> I've finalized myself" and "I really mean to return
> normally here".

Well, there is a way to tell the difference - if we just threw
GeneratorExit in, then it finalised itself, otherwise it is finishing
normally.

The only question is what to do in the outer scope in the first case.

1. Accept the StopIteration as a normal termination of the subiterator
and continue execution of the delegating generator instead of finalising
it. This is very bad as it will lead to any generator that yields again
after a yield from expression almost certainly being broken [1].

2. Reraise the original GeneratorExit.

3. Reraise the subiterator's StopIteration exception.

4. Return immediately from the delegating generator.

I actually quite like option 4, as I believe it best reflects what the
subiterator has done by trapping GeneratorExit and turning it into
"normal" termination of the subiterator, without creating a situation
where generators that use yield from a likely to accidentally ignore
GeneratorExit.

Cheers,
Nick.

[1] By "broken" in this context, I mean "close() will raise
RuntimeError", as would occur if Jacob's example used "yield val"
instead of "print val", or as occurs in the following normal generator:

>>> def gen():
...   try:
...     yield
...   except GeneratorExit:
...     pass
...   yield
...
>>> g = gen()
>>> g.next()
>>> g.close()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
RuntimeError: generator ignored GeneratorExit


-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia
---------------------------------------------------------------



More information about the Python-ideas mailing list