[Python-Dev] GeneratorExit is unintuitive and uneccessary
Phillip J. Eby
pje at telecommunity.com
Wed Aug 23 16:35:42 CEST 2006
I rather like it, actually. I don't recall there being any real reasons to
catch a GeneratorExit exception, but even if there were, you could do the
equivalent like this:
try:
closed = True
yield 1
closed = False
finally:
if closed:
# special closing code
Unfortunately, this is a pretty major change to be making to the
specification (PEP 342) when we've just released 2.5c1; it seems like
something that requires at least a beta release.
But aside from that, it seems like a fairly neat solution to the
problem. I'd like to hear from Jython and IronPython representatives
regarding implementability for those platforms, though. Our original
assumption was that if they could implement throw() then they could clearly
implement close(), since close() was defined in terms of throw(). An
asynchronous return might be another matter. But if that hurdle is
crossable, then I agree that modelling close() as an early return is more
intuitive, eliminates a built-in exception, etc.
At 03:17 PM 8/22/2006 +0200, Igor Bukanov wrote:
>Consider the following example:
>
>for i in range(3):
> try:
> print i
> break
> except:
> print "Unexpected exception!"
> finally:
> print "Finally"
>
>When executed, it naturally prints
> 0
> Finally
>since break does not use exceptions to transfer the control and as
>such can not be stopped using catch-all exception handler.
>
>Now consider a similar example using generators:
>
>def gen():
> for i in range(3):
> try:
> yield i
> except:
> print "Unexpected exception!"
> finally:
> print "Finally"
>
>for i in gen():
> print i
> break
>
>This example prints:
> 0
> Unexpected exception!
> Finally
> Exception exceptions.RuntimeError: 'generator ignored GeneratorExit'
>in <generator object at 0xb7daaa8c> ignored
>
>Suddenly with generators a program can mess with control transfer
>since it uses explicit GeneratorExit which can be caught and ignored.
>This is unintuitive IMO.
>
>This example also suggests how to fix generators. One just need to
>change the close method so it would cause return executed right after
>the yield instead of throw.
>
>I.e. replace the current text from
>http://www.python.org/dev/peps/pep-0342/
>
>4. Add a close() method for generator-iterators, which raises
>GeneratorExit at the point where the generator was paused. If the
>generator then raises StopIteration (by exiting normally, or due to
>already being closed) or GeneratorExit (by not catching the
>exception), close() returns to its caller. If the generator yields a
>value, a RuntimeError is raised. If the generator raises any other
>exception, it is propagated to the caller. close() does nothing if the
>generator has already exited due to an exception or normal exit.
>
>by simpler one:
>
>4. Add a close() method for generator-iterators, which executes normal
>return at the point where the generator was paused. If the generator
>then raises StopIteration (by exiting normally, or due to already
>being closed), close() returns to its caller. If the generator yields
>a value, a RuntimeError is raised. If the generator raises any other
>exception, it is propagated to the caller. close() does nothing if the
>generator has already exited due to an exception or normal exit.
>
>This not only fixes the above discrepancy between normal flow control
>and generators, removes GeneratorExit and simplifies the generator
>protocol, but also bring a new feature allowing to have easy to grasp
>feature table of the iterator methods:
>
>next: continue after yield
>throw: raise after yield
>close: return after yield
>
>Regards, Igor
>_______________________________________________
>Python-Dev mailing list
>Python-Dev at python.org
>http://mail.python.org/mailman/listinfo/python-dev
>Unsubscribe:
>http://mail.python.org/mailman/options/python-dev/pje%40telecommunity.com
More information about the Python-Dev
mailing list