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@gmail.com | Brisbane, Australia ---------------------------------------------------------------