什么是在生成器内部时触发上下文管理器的__exit__?

Cua*_*due 6 python garbage-collection generator contextmanager

我正在制作像使用生成器作为协程的任务调度程序.在下面的代码中,我需要print cleanup确定性地执行.

从我的交互看来,将对象释放到垃圾收集器会导致上下文管理器退出.但是,我知道最好不要依赖GC的时间.它真的是GC调用__exit__它还是另一种机制?

我怎么能严格强迫print 'cleanup'

>>> from contextlib import contextmanager
>>> @contextmanager
... def foo():
...     print 'setup'
...     try:
...         yield
...     finally:
...         print 'cleanup'
... 
>>> def bar():
...     with foo():
...         while True:
...             yield 'bar'
... 
>>> b = bar()
>>> b.next()
setup
'bar'
>>> b = None
cleanup
Run Code Online (Sandbox Code Playgroud)

Mar*_*ers 5

是的,GC正在调用__del__生成器的清理钩子,这反过来又引发了GeneratorExit生成器函数以退出生成器(通过调用generator.close()).

这意味着__exit__只要从内存中清除生成器函数,就会调用上下文管理器挂钩.

您可以先自己手动关闭发电机,使用generator.close():

b.close()
Run Code Online (Sandbox Code Playgroud)

  • 值得注意的是,在CPython中,它很容易避免`close()`调用,因为生成器一旦无法访问就会被最终确定,但这是一个实现细节,并且不会以相同的方式工作在Pypy,Jython或IronPython中.因此,如果你需要及时退出生成器(或者根本就退出!),你肯定应该明确地调用`close()`. (3认同)