我们说我们上了一堂课' A'它本身就是一个上下文管理器,所以它实现了
def __enter__()
def __exit__()
接口。它对客户端代码有效,可以使A' A'对象直接使用with
语句。
现在,我们还有另一个班级' B'它封装了其他功能,并使用了A'宾语。
如果我们想要' B'作为一个上下文管理器,以及管理它的正确方法' A'实例
{' B'上的__enter__
和__exit__
的实施是否应该在它的A对象实例上分别调用__enter__
和__exit__
?或者有更好的方法吗?
举一个具体的例子(这是不是我在我的应用程序中使用的东西,它只是我想到的第一个非抽象的例子)考虑两个类
DatabaseConnection
DatabaseConnectionPool
在其上使用单个DatabaseConnection
是有效的,因此DatabaseConnection
实现了上下文管理器接口。
DatabaseConnectionPool
使用了几个DatabaseConnections
以及其他位和bob。使用DatabaseConnectionPool
(即"使用")应该对其DatabaseConnection
个实例进行设置和拆除(以及其他可能要做的事情)< / p>
更新:我已经编写了一些测试代码,我希望它能提供以下输出:
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
代码:
class Inner(object):
def __enter__(self):
print "Enter invoked on Inner"
return self
def __exit__(self, typ, val, tb):
print "Exit invoked on inner"
def do_foo(self):
print "do_foo invoked!"
class Outer(object):
def __init__(self):
self._inner = Inner()
def __enter__(self):
print "Enter invoked on Outer"
with self._inner as ctx:
return self
def __exit__(self, typ, val, tb):
print "Exit invoked on outer"
with Outer() as outer:
print "Within outer context..."
outer._inner.do_foo()
print "Still using outer..."
print "Done using outer"
关于如何使这项工作的任何想法?
答案 0 :(得分:0)
这真的是一个设计问题和判断电话。我将提出以下建议:
池类实例提供上下文,然后根据需要以编程方式使用数据库连接实例。但这比为每个数据库实例简单地调用__enter__
和__exit__
要复杂一些,而且我认为你不应该尝试这样做,他们并不打算这样做那个目的。在这种情况下,我建议直接使用数据库实例的上下文管理器。
如果你想使用他们的上下文管理器,这样的东西会起作用:
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