Python 如何将子上下文的管理委托给父上下文

Python 如何将子上下文的管理委托给父上下文,python,contextmanager,Python,Contextmanager,假设我们有一个类“A”,它本身就充当上下文管理器,因此它实现了 def __enter__() def __exit__() 接口。客户端代码使用with语句直接生成“A”对象是有效的 现在,我们还有另一个类“B”,它封装了其他功能,还使用了“A”对象 如果我们想让“B”也充当上下文管理器,那么管理“a”实例的正确方法是什么 在“B”调用\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu和\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu

假设我们有一个类“A”,它本身就充当上下文管理器,因此它实现了

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