AnastasiiaEg
@AnastasiiaEg

Как запустить два параллельных процесса бота: бесконечную функцию, проверяющую имеются ли обновления, и обработчики событий и сообщений?

как сделать так, чтобы start_checking_price и dp.start_polling() работали одновремнно
помогите, пожалуйста, уже чего только не пробовала, не понимаю как это сделать

async def main():
    my_bot = Bot(token=TOKEN)
    dp = Dispatcher(bot=my_bot)
    dp.include_router(router)

    async def start_checking_price(wait_for: int):
        while True:
            results = await price_check.check_and_update_prices()
            for user_id, message in results.items():
                try:
                    await my_bot.send_message(user_id, message)
                except Exception as e:
                    print(f"Не удалось отправить сообщение: {e}")
            await asyncio.sleep(wait_for)

    await asyncio.create_task(start_checking_price(1800))

    try:
        await dp.start_polling()
    finally:
        await my_bot.close()


if __name__ == '__main__':
    asyncio.run(main())
  • Вопрос задан
  • 158 просмотров
Решения вопроса 1
Vindicar
@Vindicar
RTFM!
Надо хоть немножечко осознавать, как работает asyncio.
create_task() возвращает объект класса Task, представляющий собой фоновую задачу. Эта задача уже запланирована к выполнению в рабочем цикле (loop) asyncio, и будет выполняться в фоне пока текущая корутина ожидает какой-нибудь другой операции.

Но если тебе надо дождаться завершения работы задачи, ты можешь сделать await на этом объекте.
Тогда текущая корутина приостановится, пока задача не завершится, и получит или возвращённое задачей значение, или выкинутое задачей исключение.
А теперь посмотри на свой код:
await asyncio.create_task(start_checking_price(1800))

Ты создаёшь задачу - и тут же говоришь программе, что тебе надо дождаться её завершения!
Ну как бы программа и делает в точности то, что ты от неё требуешь...
Подчёркиваю красным: await asyncio.create_task(some_coro(...)) не имеет смысла практически никогда! Если тебе нужно запустить корутину и дождаться результата, делаешь просто await some_coro(...).
А вот если тебе нужно запустить корутину параллельно текущей... Получится что-то типа такого:
# ...
    check_task = asyncio.create_task(start_checking_price(1800))  # нету await, мы не ждём созданную задачу!

    try:
        await dp.start_polling()
    finally:
        check_task.cancel()  # отменяем корутину
        # внутри start_checking_price() текущий выполняемый await выкинет исключение CancelledError
        # это исключение всплывёт наружу, если мы сделаем await, и позволит отработать 
        # блокам finally, with и т.п. инструментам. Также можно явно поймать это исключение,
        # чтобы обработать отмену корутины. Но в твоём случае это не требуется.
        try:
            await check_task  # даём корутине отработать завершение
        except asyncio.CancelledError:  # ловим всплывшее CancelledError
            pass  # всё ок, никакие действия не требуются
        await my_bot.close()
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
fenrir1121
@fenrir1121
Начни с документации
Не читай про мультипроцессинг, читай про asyncio.gather или asyncio.wait :)
Ответ написан
@itsoftoff
Почитай про multiprocessing.Process)
Ответ написан
Комментировать
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы