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. - Jacob