
Description
Is your feature request related to a problem?
If you decorate a generator function with @contextlib.contextmanager
and use the context manager cm
inside a generator function, the context manager's __exit__
will not be always be called because the generator raises GeneratorExit
, which ends the generator that defines cm
.
Notice that cm exit
never appears, as cm
's __exit__
is never called.
from __future__ import generator_stop
import contextlib
import weakref
import sys
@contextlib.contextmanager
def cm():
print("cm enter")
a = yield
print('cm exit')
def genfunc():
with cm():
print("stepping")
yield
def main():
gen = genfunc()
ref = weakref.ref(gen, print)
next(gen)
if __name__ == "__main__":
main()
Output:
cm enter
stepping
<weakref at 0x7f4739e38e08; dead>
Describe the solution you'd like
Generator functions decorated with @contextlib.contextmanager
should not be used in generators unless the context manager has finally:
@contextlib.contextmanager
def cm():
try:
yield
finally:
# cleanup code here
...
or specifically handles GeneratorExit
:
@contextlib.contextmanager
def cm():
try:
yield
except GeneratorExit:
# cleanup code here
...
Additional context
Add any other context about the feature request here.