Форум сайта python.su
Не могу понять какой от него толк, если внутри него всё равно необходимо писать try…finally?
import contextlib @contextlib.contextmanager def make_context(): print ' entering' try: yield {} except RuntimeError, err: print ' ERROR:', err finally: print ' exiting'
import contextlib @contextlib.contextmanager def make_context(name): print 'entering:', name yield name print 'exiting :', name with make_context('something'): print 'middle' raise Exception('something')
Офлайн
Потом пишем:
with make_context(name): do_some_work_with_that_name()
Офлайн
Lexander
и гарантированно печатаем ‘exiting’
import contextlib @contextlib.contextmanager def make_context(name): print 'entering:', name yield name print 'exiting :', name with make_context('something'): print 'middle' raise Exception('something')
Отредактировано plusplus (Ноя. 10, 2013 17:23:29)
Офлайн
Оно с исключениями никак не связано. Это используют для того чтобы повысить читабельность в случаях когда нужно что-то выполнить перед вступлением и перед выходом из контекста
как тут вон
Отредактировано sergeek (Ноя. 10, 2013 17:47:15)
Офлайн
plusplusВ этом примере выход идет раньше на строчке с yield и с исключениями это действительно не связано.
У меня не пишет, ЧЯДНТ?
Офлайн
Давайте зайдем с другого конца.
Менеджер контекста, создаваемый с помощью with нужен для правильного завершения операций внутри контекста.
Так и с @contextlib.contextmanager.
Использовать его нужно именно в этих случаях, когда нужно гарантировать, чтобы вне зависимости от ошибок или исключений внутри создаваемого контекста, после выхода из контекста состояние программы было предсказуемым.
Пример.
Нужно собрать заархивированные данные последовательно из нескольких источников достаточно большого объема и слить их вместе, обработать и удалить все временные данные.
По одному файлу для каждого источника.
Создаем контекст.
Запускаем внутри функцию, которая сохраняет архивы в temp, там же их распаковывает и сливает в один файл.
Потом этот файл копируем куда нам нужно.
Так как во время процедуры работы с файлами могут возникнуть исключения, то нам нужно гарантировать удаления всех созданных нами временных файлов из temp.
Вот именно этот код удаления мы и поместим в finally созданного с помощью @contextlib.contextmanager контекста.
Офлайн
Отвечая на первый вопрос: какой толк?
Одна функция с декоратором или класс с двумя методами, есть разница?
В зависимости от задачи я, как использую этот декоратор, так и не ленюсь, пишу класс. Что вообще за вопрос такой. Ну и на всякий случай, мало ли, через `yield` возвращается значение, которое становится доступным в `with`, если определяется переменная после `as`. В `contextmanager` 4 строчки кода, но возможно TC поленился их изучить.
Теперь всё, все покровы сорваны, больше секретов в этой тайной технологии не осталось, ты посвящён в ближний круг :-).
..bw
Офлайн