At 13:50 26.08.2003 -0700, Guido van Rossum wrote:
The spec needs to define clearly what should happen if the generator catches and ignores the exception, e.g.:
def forever(): while True: try: yield None except: pass
f = forever() f.next() f.close()
Clearly at this point the generator reaches the yield again. What should happen then? Should it suspend so that a subsequent call to f.next() can receive another value? Or should reaching yield after the generator is closed raise another exception? I'm leaning towards the latter, despite the fact that it will cause an infinite loop in this case -- that's no different when you have a print statement instead of a yield statement.
try: ... yield ... except: # or except Exception raise a new different exception
is not a clear-cut situation. close should probably propagate exceptions different from CloseGenerator but here the right thing to do is fuzzy.
It also another case of the problems of too broad-catching except clauses, in some sense the exception generated by close is like an async exception like KeyboardInterrupt.
Another comment on Samuele's PEP: It is sort of sad that the *user* of a generator has to know that the generator's close() must be called. Normally, the beauty of using a try/finally for cleanup is that your callers don't need to know about it. But I see no way around this. And this is still an argument that pleads against the whole thing, either PEP 288 or Samuele's smaller variant: the usual near-guarantee that code in a finally clause will be executed no matter what (barring fatal errors, os._exit() or os.execv()) does not apply. And this was the original argument against allowing yield inside try/finally. But the need for cleanup is also clear, so I like Samuele's KISS compromise.
yes, we cannot totally win.