I am trying to yield a context manager that is created in a with statement. However, something that I don't understand happens: the context manager is closed before it is yielded, even though the execution in the generator did not exit the scope of the with. For example:
class CM:
  def __enter__(self):
    print('enter cm')
    return self
  def __exit__(self, exc_type, exc_val, exc_tb):
    print('exit cm')
def make_foo():
  with CM() as cm:
    print('before yield')
    yield cm
  print('after yield')
print('before make_foo')
foo = next(make_foo())
print('after make_foo')
outputs
before make_foo
enter cm
before yield
exit cm
after make_foo
I saw this thread on a related topic, and the answer is about time when the object is garbage collected -- however why would cm be garbage collected before it is returned to be used by the caller here?
EDIT
When writing instead
foo_maker = make_foo()
foo = next(foo_maker)
then the CM is not closed -- so it seems that the CM is indeed GC because the generator is GC. But shouldn't it left alone since it is returned and potentially used after?
 
    