在生成器内部时,上下文管理器的“退出”何时触发?

2024-04-25 08:17:21 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在制作类似任务调度器的东西,使用生成器作为协同程序。在下面的代码中,我需要确定地执行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

Tags: 对象代码foodefsetupbargc垃圾
2条回答

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

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

您可以先手动关闭生成器,使用^{}

b.close()

你必须让发电机退出。如果发电机的性质是寻找永远,你可以使用一般投掷()在生成器中引发异常。在

实际上,我只是看了一下生成器的规范,它们有一个close()方法可以做到这一点(它在生成器内部引发了一个GeneratorExit()异常)。所以打个电话吧发电机关闭()完成后,任何上下文管理器都将调用它们的exit方法。生成器将吃掉异常,因此不需要将close()调用包装在try块中:

>>> b= bar()
>>> b.next()
setup
'bar'
>>> b.close()
cleanup
>>>

相关问题 更多 >