Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x 在生成器中使用上下文管理器是否会导致资源泄漏?_Python 3.x_Generator_Contextmanager - Fatal编程技术网

Python 3.x 在生成器中使用上下文管理器是否会导致资源泄漏?

Python 3.x 在生成器中使用上下文管理器是否会导致资源泄漏?,python-3.x,generator,contextmanager,Python 3.x,Generator,Contextmanager,我有一个从上下文管理器生成的函数: def producer(pathname): with open(pathname) as f: while True: chunk = f.read(4) if not chunk: break yield chunk 当生成器完全被消耗时,这不是问题,因为在上一次迭代中,生成器在yield语句之后恢复执行,循环中断,我们很好地退

我有一个从上下文管理器生成的函数:

def producer(pathname):
    with open(pathname) as f:
        while True:
            chunk = f.read(4)
            if not chunk:
               break
            yield chunk
当生成器完全被消耗时,这不是问题,因为在上一次迭代中,生成器在yield语句之后恢复执行,循环中断,我们很好地退出了上下文管理器

但是,如果发电机仅部分耗电,并且没有更多的用户完全耗电,发电机是否会永远处于暂停状态?在这种情况下,我们将永远不会退出上下文管理器。这是否意味着该文件将在程序执行的其余部分保持打开状态?或者至少在发电机被垃圾收集之前?这是一个我应该自己处理的紧急情况,还是可以依靠Python运行时及时关闭悬挂的上下文管理器



FWIW,我见过,但我不认为他们真的回答了同样的问题。除非我遗漏了什么?

如果您未能使用整个生成器,则在对生成器进行垃圾收集之前不会清理上下文管理器,如果涉及引用周期,或者您在非CPython解释器上运行,则可能需要相当长的时间

您可以通过关闭生成器迭代器来解决此问题;所有生成器函数在生成的生成器迭代器上提供,该迭代器在其中引发
GeneratorExit
;异常通过语句和类似语句从
中冒泡出来,以确保它们被彻底清除

要使其在保证的时间点发生,您可以确保发电机本身关闭:

 from contextlib import closing

 with closing(producer(mypath)) as produced_items:
     for item in produced_items:
         # Do stuff, maybe break loop early

即使您
中断
返回
,或引发异常,带有
控制生成的项目的
关闭
它,这将反过来调用
清理,其中包含
语句。

这是问题吗?-这是“理所当然的”:在这种情况下,上下文管理器受生成器控制,因此服从生成器的“挂起”特性。感谢@Roman的评论。这是一个问题吗?我想我没有我希望的那么清楚。我不是在质疑上下文管理器被暂停的事实。但事实上,如果没有更多的消费者使用它,它可能会永远被暂停。