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
уже будет__exit__
ed задолго до началаMyApp.__exit__
. - person jonrsharpe   schedule 02.07.2015__enter__
или первого__exit__
другое соединение не зависало. При этом рассмотритеcontextmanager
. - person bereal   schedule 02.07.2015