Назовите основные функции модуля asyncio в Python

Ответ

Модуль asyncio предоставляет инфраструктуру для написания однопоточного конкурентного кода с использованием корутин. Ключевые функции:

  • asyncio.run(coro): Высокоуровневая точка входа для запуска асинхронной программы. Автоматически создает и управляет циклом событий (event loop).

  • asyncio.create_task(coro): Планирует асинхронную функцию для параллельного (конкурентного) выполнения в цикле событий. Немедленно возвращает объект Task, не дожидаясь завершения корутины.

  • asyncio.gather(*aws): Запускает несколько асинхронных операций одновременно и возвращает список их результатов после того, как все они будут завершены.

  • asyncio.sleep(delay): Неблокирующая пауза. Приостанавливает выполнение текущей корутины на delay секунд, позволяя циклу событий выполнять другие задачи.

  • asyncio.wait_for(aw, timeout): Ожидает завершения асинхронной операции с указанным таймаутом. Если время истекло, вызывает исключение asyncio.TimeoutError.

  • asyncio.to_thread(func, *args): Асинхронно запускает блокирующую (синхронную) функцию в отдельном потоке, не блокируя основной цикл событий. Это основной способ интеграции legacy-кода.

Пример использования:

import asyncio
import time

async def fetch_data(source: str):
    print(f"Начинаю загрузку из {source}...")
    await asyncio.sleep(1) # Имитация I/O операции
    print(f"Загрузка из {source} завершена.")
    return {"source": source, "data": "..."}

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

    # Запускаем обе задачи конкурентно
    task1 = asyncio.create_task(fetch_data("API"))
    task2 = asyncio.create_task(fetch_data("DB"))

    # Ожидаем завершения обеих задач
    results = await asyncio.gather(task1, task2)
    print(f"Получены результаты: {results}")

    end_time = time.time()
    print(f"Все операции заняли {end_time - start_time:.2f} секунд.")

# Запускаем основную корутину
asyncio.run(main())
# Вывод покажет, что общее время выполнения ~1 секунда, а не 2.

Ответ 18+ 🔞

Давай разберём эту асинхронную хрень, как есть. Ну, модуль asyncio, блядь, — это такая штука, которая позволяет твоему однопоточному коду делать вид, что он делает кучу дел одновременно. Не путай с многопоточностью, тут всё в одном потоке вертится, но по-хитрому.

Вот основные инструменты, без которых ты нихуя не сделаешь:

  • asyncio.run(coro): Это типа главная дверь в этот асинхронный бардак. Запускаешь свою главную корутину, а она уже внутри сама создаёт этот самый цикл событий, этот вечный двигатель, который всё и крутит. Просто вызвал — и поехали.

  • asyncio.create_task(coro): А вот это, сука, ключевая вещь! Ты говоришь циклу: «Слушай, вот эту штуку (coro) мне нужно выполнить, но я не буду на неё тут же ждать, пусть себе работает на фоне». Функция сразу же возвращает тебе объект Task (задачу) и говорит «пошёл нахуй, делай что хочешь дальше». А задача уже тихонько себе планируется на выполнение. Без этого — никакой конкурентности, будет просто последовательный вызов.

  • asyncio.gather(*aws): Ты накидал кучу задач через create_task, а теперь хочешь подождать, пока они все дохуяриваются. Вот gather как раз для этого. Он запускает их всех и возвращает результаты, когда последняя ленивая жопа закончит. Удобно, ёпта.

  • asyncio.sleep(delay): Это не time.sleep, который всё заблокирует и уснёт! Это асинхронная поспать. Корутина говорит: «Я тут подожду секундочку, а ты, цикл событий, иди другие дела делай, не стой столбом». Через секунду она проснётся и продолжит.

  • asyncio.wait_for(aw, timeout): Ждёшь чего-то, а оно тупит. Чтобы не ждать до второго пришествия, оборачиваешь в wait_for с таймаутом. Не успело — получи asyncio.TimeoutError в ебало и иди дальше.

  • asyncio.to_thread(func, *args): О, это спасение, когда у тебя есть старый, кривой, блокирующий код, который никуда не годится для асинхронщины. Этой функцией ты вышвыриваешь эту тяжёлую синхронную работу в отдельный поток, чтобы она не забивала мозги твоему главному циклу. Интеграция легаси, так сказать.

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

import asyncio
import time

async def fetch_data(source: str):
    print(f"Начинаю загрузку из {source}...")
    await asyncio.sleep(1) # Прикидываемся, что ходим в сеть или в базу
    print(f"Загрузка из {source} завершена.")
    return {"source": source, "data": "..."}

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

    # Создаём две задачи. Они начинают выполняться КОНКУРЕНТНО, ёба!
    task1 = asyncio.create_task(fetch_data("API"))
    task2 = asyncio.create_task(fetch_data("DB"))

    # А теперь ждём, пока обе эти бандуры не отработают
    results = await asyncio.gather(task1, task2)
    print(f"Получены результаты: {results}")

    end_time = time.time()
    print(f"Все операции заняли {end_time - start_time:.2f} секунд.")

# Поехали!
asyncio.run(main())
# В выводе увидишь, что всё заняло около секунды, а не две, потому что спали они одновременно, хитрожопые.

Вот и вся магия. Главное — понять, что await это не блокировка, а точка, где корутина может сказать «стоп, я подожду, давай другую задачу». А create_task — это команда «начинай делать это параллельно». Всё остальное — детали, блядь.