[Python-ideas] Yield-From: GeneratorExit?

Bruce Frederiksen dangyogi at gmail.com
Mon Mar 23 21:27:47 CET 2009


Jacob Holm wrote:
> Bruce Frederiksen wrote:
>> This is a valid point. But consider:
>>
>> 1. The delegating generator has no way to stop the subgenerator 
>> prematurely when it uses the yield from. So the yield from can only 
>> be stopped prematurely by the delegating generator's caller. And then 
>> the subgenerator would have to be communicated between the caller to 
>> the delegating generator somehow (e.g, passed in as a parameter) so 
>> that the caller could continue to use it. (And the subgenerator has 
>> to be a generator, not a plain iterator). 
> "...subgenerator has to be a generator" is not entirely true. For 
> example, if the subiterator doesn't have send, you can send a non-None 
> value to the generator and that will raise an AttributeError at the 
> yield from. If it doesn't have throw, you can even throw a 
> StopIteration with a value to get that value as the result of the 
> yield-from expression, which might be useful in a twisted sort of way. 
> In both cases, the subiterator will only be closed if the yield-from 
> expression actually closes it. So it is definitely possible to get a 
> non-generator prematurely finalized.
But non-generators don't have a close (or throw) method.  They lack the 
concept of "finalization".  Only generators have these extra methods.  
So using a subiterator in yield from isn't an issue here.  (Or am I 
missing something)?
> Well, if the subiterator is a generator that itself uses yield-from, 
> the need to wrap it would destroy all possible speed benefits of using 
> yield-from. So if there *is* a valid use case for yielding from a 
> shared generator, this is not really a solution unless you don't care 
> about speed.
Yes, there is a performance penalty in this case.  If the wrapper were 
written in C, then I would think that the penalty would be negligible.  
Perhaps offer a C wrapper in a standard library??
> Note that with explicit close, my argument for special-casing 
> GeneratorExit by adding "except GeneratorExit: raise" weakens. The 
> GeneratorExit will be delegated to the deepest generator/iterator with 
> a throw method. As long as the iterators don't swallow the exception, 
> they will be closed from the finally clause in the expansion. If one 
> of them *does* swallow the exception, the outermost generator will 
> raise a RuntimeError.
Another case where close differs from throw(GeneratorExit).  Close is 
define in PEP 342 to raise RuntimeError if GeneratorExit is swallowed.  
Should the delegating generator, then, be calling close rather throw for 
GeneratorExit so that the RuntimeError is raised closer to cause of the 
exception?  Or does this violate the "inlining" goal of the current PEP?

-bruce frederiksen



More information about the Python-ideas mailing list