【发布时间】:2015-09-20 06:36:30
【问题描述】:
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 的上下文管理器运行在块的末尾,如 cmets 中所指出的那样。
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__开始之前很久就已经拥有__exit__ed。 -
第二个选项几乎不错,如果添加异常处理就可以了(这样如果第二个
__enter__或第一个__exit__失败,另一个连接不会挂起。也就是说,考虑@ 987654321@. -
@jonrsharpe,我知道这就是我一开始问的原因。
标签: python class python-2.7 contextmanager