[Python-ideas] Yield-From: GeneratorExit?
jh at improva.dk
Sun Mar 22 13:42:36 CET 2009
Nick Coghlan wrote:
> Greg Ewing wrote:
>> To do otherwise would require making a distinction that
>> can't be expressed in the Python expansion. Also, it
>> seems elegant to preserve the property that if g is a
>> generator then g.close() and g.throw(GeneratorExit) are
>> exactly equivalent.
>> What do people think about this?
> That whole question is why I suggested rephrasing the question of which
> exceptions are passed to the subiterator in Exception vs BaseException
> terms. The only acknowledged direct subclasses of BaseException are
> KeyboardInterrupt, SystemExit and GeneratorExit. The purpose of those
> exceptions is to say "drop what you're doing and bail out any which way
> you can". Terminating the outermost generator in those cases and letting
> the subiterators clean up as best they can sounds like a perfectly
> reasonable option to me. The alternative is to catch BaseException and
> throw absolutely everything (including GeneratorExit) into the
> subiterator. The in-between options that you're describing would appear
> to just complicate the semantics to no great purpose.
Well, since GeneratorExit is specifically about generators, I don't see
a problem in special-casing that one and just let everything else be
thrown at the subgenerator. I would also be Ok with just throwing
everything (including GeneratorExit) there, as that makes the
implementation of throw a bit simpler.
> Note that you may also be pursuing a false consistency here, since
> g.close() has never been equivalent to g.throw(GeneratorExit), as the
> latter propagates the exception back into the current scope while the
> former suppresses it (example was run using 2.5.2):
I believe that the "exact equivalence" Greg was talking about is the
description of close from PEP 342. It is nice that the semantics of
close can be described so easily in terms of throw.
I like the idea of not having an explicit close in the expansion at all.
In most cases the refcounting will take care of it anyway (at least in
CPython), and when there are multiple references you might actually want
to not close. Code that needs it can add the explicit close themselves
by putting the yield-from in a try...finally or a with... block.
More information about the Python-ideas