В других случаях async_task
будут выполняться после выполнения cpu_bound
. Я думал, когда мы используем ProcessPoolExecutor
задачи не должны блокировать цикл. Где я не прав?
Проблема в том, что with XXXPoolExecutor()
закрывает пул в конце блока with
. Завершение работы пула ожидает завершения отложенных задач, что блокирует цикл обработки событий и несовместимо с asyncio. Поскольку в вашем первом варианте нет оператора with
, у него нет этой проблемы.
Решение состоит в том, чтобы просто удалить оператор with
и создать пул один раз (например, на верхнем уровне или в main()
), и просто использовать в функции. Если вы хотите, вы можете явно закрыть пул, вызвав pool.shutdown()
после завершения asyncio.run()
.
Также обратите внимание, что вы никогда не ожидаете фьючерса, возвращенного loop.run_in_executor
. Это ошибка, и Asyncio, вероятно, предупредит вас об этом; вам, вероятно, следует собрать возвращенные значения в списке и ждать их, например, results = await asyncio.gather(*tasks)
. Это не только соберет результаты, но и обеспечит правильное распространение исключений, возникающих в функциях вне потока, на ваш код, а не на их удаление.