-
-
Couldn't load subscription status.
- Fork 1.2k
Labels
Enhancement ✨Improvement to a componentImprovement to a componentNeeds PRThis issue is accepted, sufficiently specified and now needs an implementationThis issue is accepted, sufficiently specified and now needs an implementation
Milestone
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.
Metadata
Metadata
Assignees
Labels
Enhancement ✨Improvement to a componentImprovement to a componentNeeds PRThis issue is accepted, sufficiently specified and now needs an implementationThis issue is accepted, sufficiently specified and now needs an implementation