Python 如何将子上下文的管理委托给父上下文
假设我们有一个类“A”,它本身就充当上下文管理器,因此它实现了Python 如何将子上下文的管理委托给父上下文,python,contextmanager,Python,Contextmanager,假设我们有一个类“A”,它本身就充当上下文管理器,因此它实现了 def __enter__() def __exit__() 接口。客户端代码使用with语句直接生成“A”对象是有效的 现在,我们还有另一个类“B”,它封装了其他功能,还使用了“A”对象 如果我们想让“B”也充当上下文管理器,那么管理“a”实例的正确方法是什么 在“B”调用\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu和\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
def __enter__()
def __exit__()
接口。客户端代码使用with
语句直接生成“A”对象是有效的
现在,我们还有另一个类“B”,它封装了其他功能,还使用了“A”对象
如果我们想让“B”也充当上下文管理器,那么管理“a”实例的正确方法是什么
在“B”调用\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu和\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu?还是有更好的办法
给出一个具体的例子(这不是我在我的应用程序中使用的,它只是第一个非抽象的例子),考虑两个类
数据库连接
DatabaseConnectionPool
单独使用一个DatabaseConnection
是有效的,因此DatabaseConnection
实现了上下文管理器接口
DatabaseConnectionPool
使用多个DatabaseConnections
以及其他位和bob。使用DatabaseConnectionPool
(即“with”)应该对其DatabaseConnection
实例进行设置和拆卸(以及它可能要执行的任何其他操作)
更新:我已经编写了一些测试代码,我希望这些代码能够提供以下输出:
Enter invoked on Outer
Enter invoked on Inner
Within outer context...
do_foo invoked!
Still using outer...
Exit invoked on inner
Exit invoked on outer
Done using outer
关于如何使这项工作成功,你有什么想法吗?这实际上是一个设计问题和判断问题。我将提出以下建议:
Enter invoked on Outer
Enter invoked on Inner
Exit invoked on inner
Within outer context...
do_foo invoked!
Still using outer...
Exit invoked on outer
Done using outer
池类实例提供了一个上下文,然后根据需要以编程方式使用DB连接实例。但这比简单地为每个DB实例调用\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu和\uuuuuuuuuuuuuuuuuuuuuuuuuuuuu。在这种情况下,我建议直接使用DB实例的上下文管理器
如果您想使用他们的上下文管理器,类似这样的方法会起作用:
def __enter__(self):
for db in self.pool:
with db as d:
d.transaction()
def __exit__(self, type, value, traceback):
pass
但如果你想自己处理错误:
def __enter__(self):
for db in self.pool:
try:
db.connection()
# ... write and transact here
def __exit__(self, type, value, traceback):
if type is None: # no errors, so close as normal
for db in self.pool:
db.close()
# ... more code here for proper error handling
“A”不是“B”的子类,而是“B”使用“A”的一个实例来完成它的工作。我更新了我的描述,希望能更好地说明我要实现的目标(复合上下文管理)。我对此进行了改进,这是一个有趣的问题。
def __enter__(self):
for db in self.pool:
try:
db.connection()
# ... write and transact here
def __exit__(self, type, value, traceback):
if type is None: # no errors, so close as normal
for db in self.pool:
db.close()
# ... more code here for proper error handling