【问题标题】:Is a context manager exited if a generator is garbage collected?如果生成器被垃圾收集,上下文管理器是否退出?
【发布时间】:2021-11-08 07:01:27
【问题描述】:

假设我们有一个像这样的简单生成器:

def generator():
    with open('example.txt', 'r') as f:
        yield f.readline()
        yield f.readline()

并像这样使用它来获取单个元素/行:

line = next(generator())

临时生成器对象被垃圾回收后上下文管理器是否关闭?

【问题讨论】:

  • @MadPhysicist,...为什么不会呢?如果生成器上没有更多句柄,那么文件上的引用计数如何高于零?即使没有使用上下文管理器,我也希望它会被关闭。
  • @MadPhysicist 所以答案是否定的?为什么这么爽快?我认为这是一个有效的问题
  • ...也就是说,我对这个问题的唯一问题是“文件是否关闭?”没有严格回答“上下文管理器是否已退出?” -- 即使没有调用上下文管理器的__exit__,文件也可以关闭。 (虽然我确实希望它被调用,而且它当然很容易测试)。
  • @CharlesDuffy 有效点。显然,该文件只应该是上下文管理器的占位符。我将编辑问题。

标签: python generator contextmanager


【解决方案1】:

with 语句与try 语句具有相同的语义,除了with 语句本身的主体之外还执行一些额外的代码。来自https://docs.python.org/3/reference/compound_stmts.html#the-with-statement"

以下代码:

with EXPRESSION as TARGET:
    SUITE

在语义上等价于:

manager = (EXPRESSION)
enter = type(manager).__enter__
exit = type(manager).__exit__
value = enter(manager)
hit_except = False

try:
    TARGET = value
    SUITE
except:
    hit_except = True
    if not exit(manager, *sys.exc_info()):
        raise
finally:
    if not hit_except:
        exit(manager, None, None, None)

所以我们的yield 表达式在try 语句中,由with 语句隐含。

来自https://docs.python.org/3/reference/expressions.html#yieldexpr

yield 表达式可以在 try 构造中的任何位置使用。如果生成器在最终确定之前没有恢复(通过达到零引用计数或被垃圾回收),则将调用生成器迭代器的 close() 方法,允许执行任何未决的 finally 子句。

with 语句隐含的finally 子句显式调用上下文管理器的__exit__ 方法,从而关闭文件。

【讨论】:

    【解决方案2】:

    我们可以测试它。答案是肯定的,已经关闭了。

    import contextlib
    @contextlib.contextmanager
    def tester():
        try:
            print("enter")
            yield 42
        finally:
            print("exit")
            
           
    def generator():
        with tester() as m:
            yield m
            
    print(next(generator()))
    

    结果:

    enter
    exit
    42
    

    【讨论】:

      猜你喜欢
      • 2016-04-03
      • 1970-01-01
      • 2011-10-05
      • 2021-05-25
      • 2014-01-31
      • 2023-03-07
      • 1970-01-01
      • 2015-07-10
      • 2011-09-29
      相关资源
      最近更新 更多