Сколько event loop’ов asyncio может быть активно в одном потоке Python

Ответ

В одном потоке Python может быть только один активный (running) event loop asyncio.

Почему так?

Event loop является центральным диспетчером, который управляет всеми асинхронными задачами, колбэками и сетевыми событиями в рамках одного потока. Наличие двух одновременно работающих диспетчеров привело бы к неопределенному поведению и конфликтам.

Хотя можно создать несколько экземпляров event loop, запустить (run_until_complete, run_forever) можно только один. Попытка запустить или получить другой event loop, когда один уже активен, вызовет ошибку RuntimeError.

Пример:

import asyncio

async def main():
    print("Основной event loop работает")
    # Попытка создать и запустить вложенный loop приведет к ошибке
    try:
        loop = asyncio.new_event_loop()
        loop.run_forever() # Эта строка вызовет RuntimeError
    except RuntimeError as e:
        print(f"Ошибка: {e}")

# asyncio.run() автоматически создает, запускает и закрывает event loop
asyncio.run(main())

Для реализации настоящего параллелизма с несколькими event loop'ами каждый из них должен работать в своем собственном потоке (threading).

Ответ 18+ 🔞

Да ты посмотри, какая история, блядь! В одном потоке Python может быть только один активный event loop asyncio, и точка.

А че, собственно, за дела такие?

Event loop — это, типа, главный диспетчер, который всем заправляет: задачами, колбэками, сетевыми пиздюлями — в рамках одного потока. Если их два запустить, то они начнут драться за ресурсы, как два кота в одном мешке, и всё пойдёт к ебеням. Неопределённое поведение, конфликты — писец полный.

Ну, создать-то их можно несколько, это не проблема. Но запустить-то (run_until_complete, run_forever) можно только один, ёпта! Попробуешь запустить второй, когда первый уже пашет — получишь RuntimeError прямо в ебало.

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

import asyncio

async def main():
    print("Основной event loop работает")
    # Попытка создать и запустить вложенный loop приведет к ошибке
    try:
        loop = asyncio.new_event_loop()
        loop.run_forever() # Эта строка вызовет RuntimeError
    except RuntimeError as e:
        print(f"Ошибка: {e}")

# asyncio.run() автоматически создает, запускает и закрывает event loop
asyncio.run(main())

Хочешь настоящего параллелизма с кучей event loop'ов? Тогда каждый из них должен сидеть в своём отдельном потоке (threading), как в отдельной камере, чтобы не перегрызлись. Вот и вся магия, в рот меня чих-пых!