Почему нельзя использовать time.sleep() в асинхронном коде Python и чем его заменить

Ответ

Использование time.sleep() в корутине полностью блокирует цикл событий (event loop) Python.

Почему это плохо?

time.sleep() — это синхронная, блокирующая операция. Она останавливает выполнение всего потока, в котором запущен event loop, не давая ему возможности переключаться на другие задачи. В результате все остальные корутины "замирают" и ждут, пока time.sleep() не завершится, что сводит на нет все преимущества асинхронности.

Правильное решение

В асинхронном коде следует использовать await asyncio.sleep(). Эта функция не блокирует поток, а лишь приостанавливает выполнение текущей корутины и возвращает управление циклу событий. Event loop в это время может выполнять другие готовые к работе задачи.

Сравнительный пример:

import asyncio
import time

async def task_with_blocking_sleep():
    print("Начало блокирующей задачи...")
    # ПЛОХО: блокирует весь event loop на 2 секунды
    time.sleep(2)
    print("Блокирующая задача завершена.")

async def task_with_async_sleep():
    print("Начало асинхронной задачи...")
    # ХОРОШО: не блокирует, передает управление event loop
    await asyncio.sleep(2)
    print("Асинхронная задача завершена.")

async def another_task():
    print("Другая задача выполняется!")

async def main():
    # Запускаем блокирующую задачу и другую задачу параллельно
    # 'another_task' не сможет выполниться, пока time.sleep() не закончится
    print("--- Тест с time.sleep() ---")
    await asyncio.gather(task_with_blocking_sleep(), another_task())

    print("n--- Тест с asyncio.sleep() ---")
    # 'another_task' выполнится немедленно, пока asyncio.sleep() ожидает
    await asyncio.gather(task_with_async_sleep(), another_task())

asyncio.run(main())

Вывод: Всегда используйте await asyncio.sleep() вместо time.sleep() в асинхронном коде для сохранения его неблокирующей природы.