Python教我们使用__enter__
和__exit__
清理对象。如果我需要创建一个使用对象必须使用上下文管理器的对象怎么办?想象一下:
from database1 import DB1
from database2 import DB2
通常,它们会被这样使用:
with DB1() as db1, DB2() as db2:
db1.do_stuff()
db2.do_other_stuff()
无论发生什么,
db1
和db2
都将运行其__exit__
函数,并清理连接、刷新等。当我把所有内容放在一个类中时,我该怎么做?这显然是不正确的,因为
db1
和db2
的上下文管理器在块结束时运行,如评论中所指出的。class MyApp(object):
def __enter__(self):
with DB1() as self.db1, DB2() as self.db2:
return self
def __exit__(self, type, value, traceback):
self.db1.__exit__(self, type, value, traceback)
self.db2.__exit__(self, type, value, traceback)
我甚至考虑做这样的事情: 实际上,这看起来是个好主意(经过一些清理):
class MyApp(object):
def __init__(self):
self.db1 = DB1()
self.db2 = DB2()
def __enter__(self):
self.db1.__enter__()
self.db2.__enter__()
return self
def __exit__(self, type, value, traceback):
try:
self.db1.__exit__(self, type, value, traceback)
except:
pass
try:
self.db2.__exit__(self, type, value, traceback)
except:
pass
编辑:修复了代码。
with DB1() ...
块在MyApp.__enter__
完成之前就结束了;self.db1
在MyApp.__exit__
开始之前就已经退出了。 - jonrsharpe__enter__
或第一个__exit__
失败,则其他连接不会挂起)。话虽如此,请考虑contextmanager
。 - bereal