围绕嵌套函数定义上下文管理器是否安全?
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
的定义。)
对于第三方库*我必须提供一个消耗一些数据的函数。我的消费实施要求将数据发布到 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
的定义。)