Python中generator被垃圾回收时其内部context manager会退出吗?
问题
假设我们有如下简单的生成器:
def generator(): with open('example.txt', 'r') as f: yield f.readline() yield f.readline()
我们按照如下方式调用它来获取单个元素/行:
line = next(generator())
请问当该调用产生的临时generator对象被垃圾回收时,其中的context manager是否会被自动关闭?
答案
会,上下文管理器会被自动关闭,对应的文件句柄会正常释放。
原理如下:
- 执行
next(generator())时,会先创建一个临时的生成器实例,运行到第一个yield位置暂停,返回读取到的第一行内容。赋值完成后这个临时生成器没有任何变量引用,会被垃圾回收器标记为待回收。 - Python的生成器被回收时,会自动在内部暂停的
yield位置抛出GeneratorExit异常。 - 该异常会触发
with语句的上下文退出逻辑,自动执行文件对象的close()方法,不需要你手动迭代完整个生成器。
你可以通过自定义上下文管理器的方式验证这个逻辑,只要在__exit__方法中增加打印逻辑,就能看到生成器被回收时,上下文的退出方法确实被调用了。
内容的提问来源于stack exchange,提问作者Sebastian Hoffmann
相关产品推荐
相关产品推荐

