Рубріки: Основы

Ключевые слова async и await в Python: синтаксис и примеры

Дмитро Сімагін

Ключевые слова async и await появились в синтаксисе языка Python в версии 3.5, вышедшей в 2015 году. В пояснении к предложению PEP 492, его автор написал, что внедрение async/await поможет сделать написание асинхронного, параллельного кода Python более простым, максимально приблизит асинхронное программирование к синхронному. 

Получилось это или нет, давайте разберем более подробно. Но сначала выясним, зачем нужны ключевые слова async и await в Python, и в каком сценарии их можно применять. 

Немного об асинхронном программировании

Ключевые слова async и await нужны для реализации асинхронности в Python. Благодаря им можно выполнять операции без блокировки основного потока выполнения приложения. 

Асинхронное программирование создает условия, при которых выполнение заданий происходит параллельно, а не поочередно. То есть, порядок выполнения не столь важен, второе задание не дожидается завершения первого. Это может быть заметно при выполнении множества операций ввода-вывода (например при обработке пользовательских запросов). Таким образом, асинхронное программирование ускоряет работу всей программы поскольку более эффективно распределяет ресурсы. 

Ключевое слово async нужно чтобы объявить асинхронную функцию. Она, в свою очередь, возвращает объект coroutine, который «ожидается» при участии await. 

async def my_async_function():
    print("Welcome")
    await asyncio.sleep(1)  # Имитирует задержку
    print("Home")

 

Теперь поговорим про await. Это ключевое слово приостанавливает выполнение асинхронной функции до момента получения результата из другой асинхронной функции. Вместо того, чтобы блокировать поток, приложение переходит к выполнению иных задач. В итоге это улучшает производительность. 

async def example():
    await my_async_function()  # Ожидаем выполнения coroutine

 

Что такое корутина (coroutine) в Python

Корутина (coroutine или сопрограмма) в языке программирования Python — это особый тип функции, который допускает приостановку и возобновление в какой-либо точке её выполнения. Этим сопрограмма отличается от привычных функций, выполнение которых происходит до конца. Еще одной особенностью сопрограмм является то, что с ней можно выполнять асинхронные и многозадачные операции внутри приложение без применения потоков или процессов. Иными словами, с сопрограммой можно писать асинхронный код, который похож на синхронный. Это делает приложение более удобочитаемой. 

Сопрограмма приостанавливается с помощью ввода await. Это освобождает управление для работы других задач. Затем, когда данные готовы, уже не нужно ждать: выполнение возобновляется. 

Как создать корутину? Для этого задания в Python есть ключевое слово async. Если его использовать перед определением функции, то функция возвращает объект coroutine. Затем его можно использовать для асинхронных задач. Пример создания корутины: 

async def my_coroutine():
    print("Start coroutine")
    await asyncio.sleep(1)
    print("End coroutine")

 

Как вызвать корутину? Корутина или сопрограмма — это не совсем обычная функция, поэтому ее нельзя вызвать напрямую. Вместо этого нужно использовать ключевое слово await, чтобы дождаться завершения её выполнения, либо запускать корутину с помощью таких конструкций, как asyncio.run(). Посмотрите на фрагмент кода:

import asyncio

async def my_coroutine():
    print("Welcome")
    await asyncio.sleep(1)  # Имитирует задержку
    print("Home")

asyncio.run(my_coroutine())  # Запускает корутину

 

Чем корутина отличается от генератора? Сопрограммы немного схожи на генераторы (использующие yield), но их задача состоит в работе сугубо с асинхронным кодом. К тому же в генераторах передача управления происходит обратно в основной код при каждом вызове yield, а в корутинах для этого применяется await. 

Асинхронность и Awaitable object в Python

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

Еще одной сферой использования ключевого слова await в Python является awaitable object (ожидаемый объект) — объект, который применяется внутри асинхронных функций. Предназначение подобных объектов в том, чтобы представлять операции, допускающие приостановку и возобновление без блокировки выполнения программы. 

Типы ожидаемых объектов (awaitable objects): 

  • Корутины: Асинхронные функции, которые создаются через async def. Они возвращают корутину, которую можно «ожидать» с помощью await.
  • Tasks (Задачи): Это своего рода обёртки вокруг корутин. При создании задачи с помощью asyncio.create_task(), возникает объект, который также является awaitable.
  • Future (Будущие объекты): Это особые объекты, используемые для представления результата какой-либо будущей асинхронной операции. Встроенные библиотеки, такие как asyncio, предоставляют такие объекты для работы с событиями и результатами операций.

Пример программы на Python с использованием ключевых слов async и await

Чтобы легче понять преимущества асинхронного программирования, давайте напишем небольшую программу работы таймера, в коде которой присутствуют async и await. 

import asyncio 

# Асинхронная функция для имитации таймера
async def timer(name: str, seconds: int):
    print(f"Таймер {name} запущен на {seconds} секунд.")
    await asyncio.sleep(seconds)  # Ожидание асинхронно
    print(f"Таймер {name} завершён.")

# Основная асинхронная функция для запуска нескольких таймеров
async def main():
    # Запускаем три таймера параллельно
    await asyncio.gather(
        timer("A", 5),
        timer("B", 4),
        timer("C", 8)
    )

# Запуск асинхронного кода
asyncio.run(main())

 

  • В коде, показанном выше, мы видим функцию timer, находящуюся в режиме ожидания в течение указанного количества секунд.
  • В функции main есть три таймера, которые запускаются одновременно с помощью asyncio.gather. Это позволяет им работать параллельно.
  • Каждый таймер работает асинхронно, поэтому приложение не блокируется во время их ожидания.

Вывод: 

Таймер A запущен на 5 секунд.
Таймер B запущен на 4 секунды.
Таймер C запущен на 8 секунд.
Таймер B завершён.
Таймер A завершён.
Таймер C завершён.

 

Это простой пример, демонстрирующий работу с асинхронными задачами и управлением временем ожидания с использованием async и await.

 

Останні статті

Что такое прокси-сервер: пояснение простыми словами, зачем нужны прокси

Прокси (proxy), или прокси-сервер — это программа-посредник, которая обеспечивает соединение между пользователем и интернет-ресурсом. Принцип…

21.11.2024

Что такое PWA приложение? Зачем необходимо прогрессивное веб-приложение

Согласитесь, было бы неплохо соединить в одно сайт и приложение для смартфона. Если вы еще…

19.11.2024

Как создать игру на телефоне: программирование с помощью конструктора

Повсеместное распространение смартфонов привело к огромному спросу на мобильные игры и приложения. Миллиарды пользователей гаджетов…

17.11.2024

Google Bard: эффективный аналог ChatGPT

В перечне популярных чат-ботов с искусственным интеллектом Google Bard (Gemini) еще не пользуется такой популярностью…

14.11.2024

Скрипт и программирование: что это такое простыми словами

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

12.11.2024

Дедлайн в разработке: что это такое простыми словами

Дедлайн (от англ. deadline — «крайний срок») — это конечная дата стачи проекта или задачи…

11.11.2024