Функції асинхронного генератора
Оновлено: 24.04.2023
Наявність виразу yield у функції чи методі, визначеному за допомогою async def, далі визначає функцію як функцію asynchronous generator.
Коли викликається функція асинхронного генератора, вона повертає асинхронний ітератор, відомий як об’єкт асинхронного генератора. Потім цей об’єкт керує виконанням функції генератора. Асинхронний об’єкт генератора зазвичай використовується в операторі async for у функції співпрограми аналогічно тому, як об’єкт генератора використовувався б у операторі for.
Виклик одного з методів асинхронного генератора повертає об’єкт awaitable, і виконання починається, коли цей об’єкт очікується. У цей час виконання переходить до першого виразу yield, де воно знову призупиняється, повертаючи значення expression_list до співпрограми очікування. Як і у випадку з генератором, призупинення означає, що весь локальний стан зберігається, включаючи поточні прив’язки локальних змінних, покажчик інструкцій, внутрішній стек оцінки та стан будь-якої обробки винятків. Коли виконання відновлюється шляхом очікування наступного об’єкта, повернутого методами асинхронного генератора, функція може продовжувати роботу точно так, якби вираз yield був просто ще одним зовнішнім викликом. Значення виразу yield після відновлення залежить від методу, який відновив виконання. Якщо використано __anext__(), результатом буде None. В іншому випадку, якщо asend() використовується, результатом буде значення, передане цьому методу.
Якщо асинхронний генератор завершує роботу раніше через break, скасування завдання виклику або інші винятки, запуститься асинхронний код очищення генератора та, можливо, викличе винятки або отримає доступ до змінних контексту в неочікуваному контексті — можливо, після час життя завдань залежить від цього, або під час завершення циклу подій, коли викликається хук збирання сміття асинхронного генератора. Щоб запобігти цьому, абонент повинен явно закрити асинхронний генератор, викликавши метод aclose(), щоб завершити генератор і остаточно від’єднати його від циклу подій.
У функції асинхронного генератора вирази yield дозволені будь-де в конструкції try. Однак, якщо асинхронний генератор не відновлено до його завершення (досягнувши нульового підрахунку посилань або збираючи сміття), тоді вираз yield у конструкції try може призвести до збою виконання очікуваного finally. У цьому випадку цикл подій або планувальник, який запускає асинхронний генератор, відповідає за виклик методу aclose() асинхронного генератора-ітератора та запуск отриманого об’єкта співпрограми, таким чином дозволяючи будь-які очікуючі finally для виконання.
Щоб подбати про фіналізацію після завершення циклу подій, цикл подій має визначати функцію finalizer, яка приймає асинхронний генератор-ітератор і, ймовірно, викликає aclose() і виконує співпрограму. Цей фіналізатор можна зареєструвати, викликавши sys.set_asyncgen_hooks(). Під час першого повторення асинхронний генератор-ітератор зберігатиме зареєстрований фіналізатор, який буде викликаний під час фіналізації. Для довідкового прикладу методу finalizer перегляньте реалізацію asyncio.Loop.shutdown_asyncgens у Lib/asyncio/base_events.py.
Вираз yield from є синтаксичною помилкою під час використання у функції асинхронного генератора.