В чем назначение ключевых слов async и await в Python

Ответ

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

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

Ключевая идея: Пока одна корутина ждет завершения I/O-операции с помощью await, цикл событий может запустить или продолжить выполнение других задач, что значительно повышает производительность I/O-bound приложений.

Пример с asyncio:

import asyncio
import time

async def fetch_data(delay):
    print("Начало загрузки данных...")
    # Имитация долгой сетевой операции
    await asyncio.sleep(delay)
    print(f"Данные загружены за {delay} сек.")
    return {"data": f"some_data_from_{delay}s_request"}

async def main():
    start_time = time.time()

    # Запускаем обе корутины конкурентно, не дожидаясь завершения каждой по очереди
    task1 = asyncio.create_task(fetch_data(2))
    task2 = asyncio.create_task(fetch_data(3))

    # Ожидаем завершения обеих задач
    result1 = await task1
    result2 = await task2

    end_time = time.time()
    print(f"Все операции завершены за {end_time - start_time:.2f} сек.")

# Запуск главной асинхронной функции
asyncio.run(main())

# Вывод будет примерно таким:
# Начало загрузки данных...
# Начало загрузки данных...
# Данные загружены за 2 сек.
# Данные загружены за 3 сек.
# Все операции завершены за 3.01 сек. (а не за 2+3=5 сек)

Важно: await можно использовать только внутри функции, объявленной с помощью async def.

Ответ 18+ 🔞

Давай разберёмся с этими async и await, а то народ, бывает, нихуя не понимает, а потом в коде пиздец творится.

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

А теперь асинхронность — это как будто ты подошёл к бармену, заказал пиво, а он тебе: «Жди, пока нальют». И вместо того чтобы тупо стоять и пялиться в потолок, ты пошёл на хуй, чипсы взял, с тёлкой поболтал, потом вернулся — а пиво уже готово. И очередь вся не стоит, а делает свои дела. Вот это и есть асинхронность, ёпта!

  • async def — это не просто функция, это корутина, такая хитрая жопа, которую можно поставить на паузу, а потом обратно запустить. Объявляешь её — и всё, функция теперь может «засыпать» и «просыпаться».
  • await — это и есть команда «спать». Говоришь await какая_то_долгая_хрень() — и всё, выполнение корутины останавливается, но программа-то не встаёт! Цикл событий (event loop) — этот главный распиздяй — идёт проверять, а нет ли других корутин, которым уже пора проснуться? И так по кругу, пока твоя операция не сделается.

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

Смотри, как это выглядит в деле:

import asyncio
import time

async def fetch_data(delay):
    print("Начало загрузки данных...")
    # Представь, что тут запрос в интернет, а не просто сон
    await asyncio.sleep(delay)
    print(f"Данные загружены за {delay} сек.")
    return {"data": f"some_data_from_{delay}s_request"}

async def main():
    start_time = time.time()

    # Создаём задачи — это как отправить двух курьеров одновременно
    task1 = asyncio.create_task(fetch_data(2))
    task2 = asyncio.create_task(fetch_data(3))

    # Ждём, пока оба курьера вернутся, но они же едут параллельно!
    result1 = await task1
    result2 = await task2

    end_time = time.time()
    print(f"Все операции завершены за {end_time - start_time:.2f} сек.")

# Запускаем всю эту карусель
asyncio.run(main())

# Вывод будет примерно таким:
# Начало загрузки данных...
# Начало загрузки данных...
# Данные загружены за 2 сек.
# Данные загружены за 3 сек.
# Все операции завершены за 3.01 сек. (а не за 2+3=5 сек, вот это магия, блядь!)

Видишь? Вторая задача заняла 3 секунды, но мы не ждали её завершения, чтобы начать первую. Они стартанули вместе, и общее время — это время самой долгой задачи, а не сумма. Красота, в рот меня чих-пых!

И запомни, ёпта: await можно юзать только внутри async def. Вылезешь с ним в обычную функцию — получишь ошибку, и будешь сидеть, чесать репу, как тот Герасим из рассказа, который только «Муму» сказать мог. Не будь как Герасим.