Consider the following Python code:
def values():
with somecontext():
yield 1
yield 2
for v in values():
print(v)
break
In this case, does Python guarantee that the generator is properly closed and, thus, that the context is exited?
I realize that it, in practice, is going to be the case in CPython due to reference counting and eager destruction of the generator, but does Python guarantee this behavior? I do notice that it does indeed not work in Jython, so should that be considered a bug or allowable behavior?
If your emphasis is on safety, you can always wrap the generator in a
contextlib.closing
- this seems like the most straightforward solution:In fact, if it were me I'd write the function as
ensuring that any user has to put this in a
with
to use it.Yes, you can use a
with
statement in a generator without issue. Python will handle the context correctly, because the generator will be closed when garbage collected.In the generator a
GeneratorExit
exception is raised when the generator is garbage collected, because it'll be closed at that time:This is part of PEP 342, where closing a generator raises the exception. Reaping a generator that has no references left should always close that generator, if Jython is not closing the generator I'd consider that a bug.
See points 4 and 5 of the Specification Summary:
The only caveat then is that in Jython, IronPython and PyPy the garbage collector is not guaranteed to be run before exiting the interpreter. If this is important to your application you can explicitly close the generator:
or trigger garbage collection explicitly.