Как работает контекстный менеджер в ПИТОНЕ
from contextlib import contextmanager
@contextmanager
def nullresource(*args, **kwargs):
try:
yield None
except:
pass
class NullResource():
def __enter__(self):
return None
def __exit__(self, *args, **kwargs):
return True
with nullresource() as r:
r.some_method()
with NullResource() as r:
r.some_method()
Не понимаю как работает контекстный менеджер. Можете объяснить, как исполнится пример кода и почему именно так?
Ответы (1 шт):
yeild прерывает функцию возвращая значение None. Эта часть аналог __enter__, тутошнее None присваивается к r.
Потом выполняется тело блока with. В этой Там возникает ошибка None object has no attribute 'some_method' потому что some_method нигде не определен.
Это исключение попадает в блок except и там игнорируется.
Во втором случае __enter__ присваивает значение r, а __exit__ выполняется при выходе из блока with.
Исключение возникшее в блоке передается в метод .__exit__(self, exc_type, exc_value, traceback) в аргументах и там никак не обрабатывется в вашем случае.
Правильный код:
from contextlib import contextmanager
@contextmanager
def nullresource(*args, **kwargs):
def somemethod():
print('somemethod')
try:
yield somemethod
except Exception as e:
print('произошла непредвиденная ошибка')
raise e
with nullresource() as r_some_method:
r_some_method()
и с классом
class NullResource():
def some_method(self):
print('NullResource().some_method()')
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
if exc_type:
print('произошла непредвиденная ошибка')
with NullResource() as r:
r.some_method()