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@python.org >http://mail.python.org/mailman/listinfo/python-dev >Unsubscribe: >http://mail.python.org/mailman/options/python-dev/pje%40telecommunity.com _______________________________________________ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com