Вопрос проверяет понимание модели исполнения asyncio и различие между конкурентностью и параллелизмом.
По умолчанию asyncio работает в одном процессе и одном потоке. Все корутины выполняются внутри одного event loop. Параллелизм достигается за счёт неблокирующего ввода-вывода, а не за счёт нескольких ядер. Дополнительные потоки или процессы используются только явно.
Asyncio — это фреймворк для конкурентного выполнения задач на основе event loop и неблокирующих операций ввода-вывода.
По умолчанию:
1 процесс
1 поток
1 event loop
Множество корутин
Все корутины:
делят один поток
переключаются в точках await
Пример:
async def handler():
await asyncio.sleep(1)
Во время await управление передаётся event loop, который может запустить другую корутину.
Asyncio:
не использует несколько ядер
не выполняет Python-код одновременно
Это конкурентность, а не параллельность.
Asyncio может использовать пул потоков для блокирующих операций:
loop.run_in_executor(None, blocking_func)
В этом случае:
создаётся ThreadPoolExecutor
блокирующий код уходит в отдельный поток
event loop остаётся отзывчивым
Для CPU-bound задач можно использовать ProcessPoolExecutor:
loop.run_in_executor(process_pool, cpu_task)
Тогда:
создаются отдельные процессы
появляется реальный параллелизм
Использовать asyncio для CPU-bound задач без executors. Это приводит к блокировке event loop и деградации всей системы.
Asyncio по умолчанию — это один поток и один процесс. Масштабирование по CPU достигается только при явном использовании процессов.