Как работает ключевое слово `await`?

Ключевое слово await используется внутри async функций для приостановки выполнения функции до тех пор, пока асинхронная операция (например, корутина или задача) не завершится. await "отпускает" цикл событий, позволяя другим корутинам выполняться, и затем возобновляет выполнение текущей корутины, когда результат асинхронной операции станет доступен. Это позволяет избежать блокировки потока выполнения и обеспечивает конкурентное выполнение операций. await может применяться только к awaitable объектам (объектам, которые имеют метод __await__).

Ключевое слово await в Python используется в асинхронных функциях (async def) и предназначено для приостановки выполнения функции до тех пор, пока не будет получен результат выполнения другого awaitable объекта (обычно корутины).

Основная функция await:

  • Приостановка выполнения: await приостанавливает выполнение текущей асинхронной функции, давая возможность event loop (циклу событий) выполнить другие задачи. Это ключевое отличие от блокирующих операций в синхронном коде, где поток выполнения полностью останавливается.
  • Передача управления Event Loop: Когда await встречает awaitable объект, он передает управление event loop. Event loop продолжает выполнять другие готовые к выполнению корутины или задачи.
  • Получение результата: Когда awaitable объект завершает выполнение и возвращает результат, await возобновляет выполнение асинхронной функции с того места, где оно было приостановлено, и получает возвращенное значение.

Awaitable объекты:

await может использоваться только с awaitable объектами. В Python 3.5 и выше, awaitable объекты включают:

  • Корутины (Coroutines): Функции, объявленные с использованием async def.
  • Задачи (Tasks): Объекты, созданные с помощью asyncio.create_task() или asyncio.ensure_future(), которые оборачивают корутину для параллельного выполнения.
  • Объекты с методом __await__(): Любой объект, реализующий метод __await__(), который должен вернуть итератор. Это позволяет создавать собственные awaitable типы.

Пример:


import asyncio

async def fetch_data(url):
    print(f"Начинаю загрузку данных с {url}")
    # Имитация асинхронного запроса (задержка)
    await asyncio.sleep(1)  # Вместо реального запроса к сети
    print(f"Данные с {url} загружены")
    return f"Данные с {url}"

async def main():
    data1 = await fetch_data("https://example.com/api/data1")
    print(f"Обработка данных 1: {data1}")
    data2 = await fetch_data("https://example.org/api/data2")
    print(f"Обработка данных 2: {data2}")

if __name__ == "__main__":
    asyncio.run(main())
    

В этом примере:

  • fetch_data - асинхронная функция, которая "загружает" данные (на самом деле просто ждет секунду).
  • await asyncio.sleep(1) приостанавливает fetch_data на 1 секунду, позволяя event loop выполнять другие задачи.
  • main - еще одна асинхронная функция, которая вызывает fetch_data дважды с помощью await.
  • asyncio.run(main()) запускает event loop и функцию main.

Важно понимать: await может использоваться только внутри асинхронных функций. Использование await вне асинхронной функции приведет к ошибке SyntaxError.

Суммируя: await - это ключевой механизм для написания асинхронного кода в Python, позволяющий выполнять операции параллельно, не блокируя основной поток выполнения, что приводит к более отзывчивым и эффективным приложениям, особенно при работе с операциями ввода-вывода (сеть, диски и т.д.).

0