[Python-Dev] Re: [Python-iterators] Python generators and try/finally..
Tim Peters
tim.one@home.com
Mon, 14 Jan 2002 19:18:40 -0500
[Neil Schemenauer]
> ...
> In practice, I think the current restriction is not a big problem.
> try/finally is allowed in code that calls generators as well as code
> called by generators. It is only disallowed in the body of generator
> itself.
It's not that severe, Neil: the only restriction is that yield cannot
appear in the try clause of a try/finally construct. try/finally can
otherwise be used freely inside generators, and yield can be used anywhere
inside a generator inside try/except/else, and even in a finally clause
(these latter assuming the yield is not also in the try clause of an
*enclosing* try/finally construct) -- just not in a try/finally's try
clause.
Here's the example from PEP 255 (also embedded in a test_generators.py
doctest, so we know for sure it works as advertised <wink>):
>>> def f():
... try:
... yield 1
... try:
... yield 2
... 1//0
... yield 3 # never get here
... except ZeroDivisionError:
... yield 4
... yield 5
... raise
... except:
... yield 6
... yield 7 # the "raise" above stops this
... except:
... yield 8
... yield 9
... try:
... x = 12
... finally:
... yield 10
... yield 11
>>> print list(f())
[1, 2, 4, 5, 8, 9, 10, 11]
>>>
[David Jeske]
>> The PEP says that there is no guarantee that next() will be called
>> again. However, there is a guaratee that either next() will be called,
>> or the Generator will be cleaned up.
Not so: Python doesn't guarantee destructors will get called by magic (see
the discussion of __del__ in the Python Reference Manual). So best practice
is to use explicit (e.g.) close() calls anyway, and if you make your
generator a method of an object, its critical resources can (conveniently,
even!) be exposed to other methods for explicit cleanup (or its __del__, if
you absolutely must).
In practice (and I've had a lot <wink>), I have yet to be so much as midly
annoyed by this restriction. So I have to echo Neil:
> We should not propagate that behavior without some careful thought. I
> would like to see some compelling arguments as to why try/finally
> should be supported inside generators.
And especially with bizarre "and 'finally' will probably get executed, but
no guarantee that it will, and there's no predicting when-- or even in which
thread --if it does, and if it does and 'finally' itself goes boom, we may
also ignore the error" semantics. As the PEP says, all of that is too much
a violation of finally's pre-generators contract to bear.
you-broke-it-you-fix-it<wink>-ly y'rs - tim