如何从 ExitStack 中删除上下文管理器

ara*_*ore 5 python stack with-statement

我有一个名为“更新程序”的长期运行进程,它已提交更新(到 ETL 系统)。更新具有通过将上下文管理器添加到更新程序的 ExitStack 来管理的资源要求。某些更新将包括新配置,这意味着必须从堆栈中释放受影响的资源,并且将添加该资源的新配置版本。我需要类似的东西:

with ExitStack() as stack:
    ctx_manager = open("file.txt")
    f = stack.enter_context(ctx_manager)
    ...
    ctx_pop(ctx_manager, stack)  # remove the given context manager from the stack
Run Code Online (Sandbox Code Playgroud)

下面是我已经开始工作的示例,但它依赖于访问受保护的成员。我希望可能有一个比这更“肮脏”的解决方案:

def ctx_pop(cm, stack):
    for item in stack._exit_callbacks:
        if item.__self__ is cm:
            break
    else:
        raise KeyError(repr(cm))
    stack._exit_callbacks.remove(item)
    item(None, None, None)
Run Code Online (Sandbox Code Playgroud)

编辑:添加已知解决方案

use*_*ica 1

contextlib.ExitStack只支持一次退出所有上下文管理器。您无法单独弹出上下文管理器。如果你想这样做,你应该使用 ExitStack 之外的其他东西来跟踪你的上下文管理器。