[Python-ideas] Yield-From: Finalization guarantees
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:
More information about the Python-ideas