[Python-ideas] Yield-From: Finalization guarantees

Jacob Holm jh at improva.dk
Tue Mar 31 01:22:22 CEST 2009


Greg Ewing wrote:
> Nick Coghlan wrote:
>
>> Well, in theory people are meant to be writing "except Exception:"
>> rather than using a bare except or catching BaseException - that's a big
>> part of the reason SystemExit, KeyboardInterrupt and GeneratorExit
>> *aren't* Exception subclasses.
>
> Yes, it probably isn't something people will do very
> often. But as long as GeneratorExit is documented as
> an official part of the language, we need to explain
> how we're dealing with it.
As my last (flawed) example shows, it is easy to accidently convert the 
GeneratorExit (along with any other uncaught exception) to a 
StopIteration if you are using a finally clause. You don't need to 
explicitly catch anything. Code that does this should be considered 
broken. Not so much because it is swallowing GeneratorExit, but because 
it swallows *any* exception. I don't think we should add special cases 
to the yield-from semantics to cater for broken code.

I even think it might have been a mistake in PEP 342 to let close 
swallow StopIteration. It might have been better if a throw to an 
already-closed generator just raised the thrown exception, and close 
only swallowed GeneratorExit. That way, you would quickly discover that 
the generator was swallowing exceptions because a call to close would 
cause a StopIteration. With that definition, we would consider any 
generator that did not (under normal conditions) raise GeneratorExit 
when thrown a GeneratorExit to be broken. Had that been the definition, 
I think we would long ago have agreed to let yield-from treat 
GeneratorExit like any other exception.

Unfortunately that is not how things work, and I am afraid that changing 
it would "break" too much code. I put "break" in quotes, because I think 
most such code is already broken in the sense that it can swallow 
exceptions that it shouldn't, such as KeyboardInterrupt and SystemExit.

Even without changing throw and close, I still think we should forward 
GeneratorExit like any other exception, and not do anything special to 
reraise it or call close on the subiterator. To me that sounds like the 
cleaner solution, and it is what the inlining principle suggests. It is 
unfortunate that you have to be a bit more careful about not swallowing 
GeneratorExit, but I think that care is needed anyway to avoid 
swallowing other exceptions as well.

>
> BTW, how official *is* it meant to be? There seems to
> be very little said about it in either the Language or
> Library Reference.
>
> The Library Ref says it's the "exception raised when a
> generator's close() method is called". The Language Ref
> says that the close() method "allows finally clauses to
> run", but doesn't say how that is accomplished.
>
> And I can't find throw() mentioned anywhere!
>
All the generator methods are described here: 
http://docs.python.org/reference/expressions.html#yield-expressions

- Jacob





More information about the Python-ideas mailing list