围绕嵌套函数定义上下文管理器是否安全?

Is it safe to define a context manager around a nested function?

对于第三方库*我必须提供一个消耗一些数据的函数。我的消费实施要求将数据发布到 API。所以我想出了下面这个结构:

def consumer_provider():

    with HttpClient() as http_client:
        
        def consumer(data):
            http_client.post(data)

        return consumer

所以我可以像这样将函数呈现给第三方库:

third_party_lib.add(consumer=consumer_provider())

在我的测试中它运行良好,但这是合法的吗?我什么时候必须期望上下文管理器释放资源(在本例中是连接池)?

* 在这种情况下是 loguru,但这对问题来说应该无关紧要

这取决于上下文管理器。在您编写的代码中,您创建的 HTTPClient 仍然存在,因为它 returns 的函数保留了对它的引用,即使 consumer_provider 中定义的变量 http_client 退出范围。

但是,HTTPClient.__exit__ 仍然在 consumer_provider returns 之前调用,因此消费者功能可能无法按预期工作。

你可能想做类似的事情

def consumer_provider():
    http_client = HttpClient()
    def consumer(data):
        with http_client:
            http_client.post(data)
    return consumer

这确保 HttpClient 对象在闭包内保持“隐藏”状态,但它的 __enter____exit__ 方法在函数被调用之前不会被调用。 (客户端是否可以被多个函数调用使用也取决于HttpClient的定义。)