@lamernoob

Почему цикл for блокирует асинхронное выполнение программы?

У меня есть функция, которая берет все аккаунты пользователей из базы данных, а затем берет каждый из них и подключается к нему. Я использую ключевое слово await перед вызовом функции pool_user, однако цикл не переходит к следующей итерации, пока происходит подключение к аккаунту, хотя в функции pool_user нет ничего, что могло бы блокировать асинхронный цикл.
async def start(bot: Bot):
    async def pool_user(account):
        user = User(account, bot)
        if await user.connect():
            users[account.id] = user
        else:
            await bot.send_message(user.owner_id, str(f"Произошла ошибка входа в аккаунт {user.name}!"))
    accounts = db.account.get_all_accounts()
    for account in accounts:
        await pool_user(account)


При этом если создать задачу для каждого аккаунта, то всё выполняется параллельно.
async def start(bot: Bot):
    async def pool_user(account):
        user = User(account, bot)
        if await user.connect():
            users[account.id] = user
        else:
            await bot.send_message(user.owner_id, str(f"Произошла ошибка входа в аккаунт {user.name}!"))
    accounts = db.account.get_all_accounts()
    for account in accounts:
        asyncio.create_task(pool_user(account))


Возможно я слабо понимаю асинхронность, но прочитав несколько статей по этому поводу мне кажется, что это должно работать.
  • Вопрос задан
  • 154 просмотра
Пригласить эксперта
Ответы на вопрос 2
@Everything_is_bad
хотя в функции pool_user нет ничего, что могло бы блокировать асинхронный цикл.
в этом цикле нет блокирования eventloop, просто с await ты ждешь результат выполнения pool_user каждого account (запускаешь по одному), а create_task запускает выполнения pool_user без этого ожидания (запускаешь сразу для всех)

то всё выполняется параллельно
не совсем, всё таки параллельно и асинхронно это разные вещи

accounts = db.account.get_all_accounts()
зато тут скорее всего есть, из-за синхронной работы с базой.
Ответ написан
Комментировать
AshBlade
@AshBlade
Просто хочу быть счастливым
Ключевое слово await заставляет ожидать завершения всей функции и только потом происходит переход к следующей итерации.
Если использовать asyncio.create_task, то создается и запускается фоновая задача - цикл продолжается после запуска этой асинхронной функции и не ждет ее завершения.

хотя в функции pool_user нет ничего, что могло бы блокировать асинхронный цикл

Во-первых, там есть подключение if await user.connect()
Во-вторых, ты отправляешь сообщение если подключиться не удалось await bot.send_message

Но в любом случае ты постоянно делаешь подключение, которое и блокирует выполнение функции
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
27 апр. 2024, в 13:49
300000 руб./за проект
27 апр. 2024, в 13:30
30000 руб./за проект
27 апр. 2024, в 13:22
600 руб./за проект