yield
выражение возвращает управление тому, что используется генератором. Генератор делает паузу в этом пункте, а это значит, что декоратор @contextmanager
знает, что код выполнен с помощью установки.
Другими словами, все, что вы хотите сделать в менеджере контекста __enter__
, должно пройти до yield
.
После того, как ваш контекст выходит (поэтому блок под with
заявление сделано), то @contextmanager
декоратора вызывается для __exit__
части протокола контекста менеджера и сделать одну из двух вещей:
Если не было никакого исключения, он возобновит генератор. Так что ваш генератор продолжает воспроизведение на yield
линии, и вы вступаете в фазу очистки, часть
Если есть исключение, декоратор использует generator.throw()
поднять это исключение в генераторе. Это будет как если бы строка yield
вызвала это исключение. Поскольку у вас есть предложение finally
, оно будет выполнено до того, как ваш генератор выйдет из-за исключения.
Таким образом, в вашем конкретном примере последовательность выглядит следующим образом:
with time_print("processes"):
Это создает менеджер контекста и вызывает __enter__
по этому вопросу.
Генератор запускает выполнение, запускается t = time.time()
.
Выражение выражения yield
приостанавливает генератор, управление возвращается к декоратору. Это берет то, что было получено, и возвращает его в инструкцию with
, если есть часть as target
.
[doproc() for _ in range(500)]
запущен и завершен.
Контекст менеджер __exit__
метод запускается, исключение не передается в.
Декоратор возобновляет генератор, он по-прежнему где она была прервана.
Введено блок finally:
и выполнен print task_name, "took", time.time() - t, "seconds."
.
Генератор выходит, декоратор __exit__
метод выхода, все сделано.
[Из документов:] (https://docs.python.org/2/library/contextlib.html#contextlib.contextmanager) «В тот момент, когда генерируется генератор, выполняется блок, вложенный в оператор« с ». Затем генератор возобновляется после выхода блока. Если в блоке возникает необработанное исключение, оно ререйзируется внутри генератора в точке где произошел доход ». –
'yield' без аргумента семантически эквивалентен' yield None' –