Nick Coghlan wrote:
Should GeneratorExit inherit from Exception or BaseException?
Currently, a generator that catches Exception and continues on to yield another value can't be closed properly (you get a runtime error pointing out that the generator ignored GeneratorExit).
The only decent reference I could find to it in the old PEP 348/352 discussions is Guido writing :
when GeneratorExit or StopIteration reach the outer level of an app, it's a bug like all the others that bare 'except:' WANTS to catch.
(at that point in the conversation, I believe bare except was considered the equivalent of "except Exception:")
While I agree with what Guido says about GeneratorExit being a bug if it reaches the outer level of an app, it seems like a bit of a trap that a correctly written generator can't write "except Exception:" without preceding it with an "except GeneratorExit:" that reraises the exception. Isn't that exactly the idiom we're trying to get rid of for SystemExit and KeyboardInterrupt?
The last comment I heard from Guido on this topic was that he was still thinking about it.
However, I now have an additional data point - if GeneratorExit inherits directly from BaseException, it makes it much easier to write exception handling code in generators that does the right thing on both Python 2.4 and 2.5.
In 2.4, PEP 342 hasn't happened, so "except Exception:" can't misbehave in response to GeneratorExit (the latter doesn't exist, and nor does generator finalisation). If GeneratorExit inherits directly from BaseException, the code still does the right thing since the exception isn't caught.
OTOH, if GeneratorExit inherits from Exception (as in current SVN), then two things will be needed to make the generator work correctly:
1. add a preceding exception clause to fix Python 2.5 behaviour: except GeneratorExit: raise except Exception: # whatever
2. add header code to the module to make it work again on Python 2.4:
try: GeneratorExit except NameError: class GeneratorExit(Exception): pass
IMO, that would be an ugly bit of backwards incompatibility (even though I wouldn't expect such broad exception handling in generators to be at all common).