Как в Python asyncio поведет себя Event Loop, если корутина выполняет CPU-bound задачу

Ответ

Нет, Event Loop не переключится на другую задачу. Он будет заблокирован до тех пор, пока CPU-bound операция не завершится.

Почему так происходит?

asyncio использует модель кооперативной многозадачности. Это означает, что корутина должна явно передать управление обратно в Event Loop с помощью ключевого слова await. CPU-bound задачи (например, сложные вычисления, обработка изображений) не содержат await, поэтому они монополизируют поток выполнения и блокируют весь цикл событий.

Проблема

В этом примере other_task никогда не получит управление, пока cpu_bound_task не завершит свои долгие вычисления.

import asyncio
import time

async def cpu_bound_task():
    print("CPU-bound задача началась...")
    # Симуляция долгой блокирующей операции
    sum(i*i for i in range(10**7))
    print("CPU-bound задача завершена.")

async def other_task():
    print("Другая задача выполняется в фоне...")
    await asyncio.sleep(1)

async def main():
    # other_task не сможет выполниться, пока cpu_bound_task работает
    await asyncio.gather(cpu_bound_task(), other_task())

# asyncio.run(main()) # Этот код заблокирует Event Loop

Решение

Для выполнения блокирующих CPU-bound задач в асинхронном коде следует использовать loop.run_in_executor(). Этот метод выносит выполнение функции в отдельный поток (или процесс), не блокируя Event Loop.

import asyncio

async def cpu_bound_task_fixed():
    print("CPU-bound задача началась в executor...")
    loop = asyncio.get_running_loop()
    # Выполняем блокирующую функцию в пуле потоков по умолчанию
    await loop.run_in_executor(
        None, 
        lambda: sum(i*i for i in range(10**7))
    )
    print("CPU-bound задача завершена.")

async def main_fixed():
    # Теперь задачи выполняются конкурентно
    await asyncio.gather(cpu_bound_task_fixed(), other_task())

asyncio.run(main_fixed())

Таким образом, для CPU-bound операций необходимо использовать экзекуторы, чтобы сохранить отзывчивость асинхронного приложения.