last day (15 days later) » 

16:59
0
Q: Сбивается бот в новом потокен aiogram

Andrey Lakiasync def check(): print("Check...") while 1: if ... await bot.send_message(...) def startup(): loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) loop.run_until_complete(check()) loop.close() async def on_startup(dp): threading.Thre...

тогда вы мне ответите с решением?
Нельзя использовать одни и те же asyncio-объекты из двух разных event loop'ов. Что вы пытаетесь сделать и зачем? Почему вместо простого asyncio.create_task(check()) вы решили нагородить целый отдельный поток?
asyncio.create_task не переводит в отдельный поток мою функцию, функцию нужно именно так, чтобы работала и проверка в функции и сам бот для пользователей
В asyncio для этого не нужен отдельный поток, достаточно простого create_task
А если же вы прям очень сильно принципиально хотите отдельный поток — значит в функции check избавьтесь от любых пересечений с объектами из первого event loop'а, в частности уберите использование объекта bot
при использовании create_task мой бот останавливается, и пользоваться им нельзя, а сама функция начинает корректно работать. а объект bot нужен, если проверка прошла успешно, он уведомляет меня
16:59
Если вы в функции check выполняете какие-то синхронные действия, то вместо того, чтобы городить отдельный поток с отдельным event loop'ом, лучше просто запустите синхронную функцию с синхронными действиями через run_in_executor и асинхронно дождитесь завершения её работы через обычный await
Ну и да, это самое ожидание завершения её работы можно запустить отдельно всё через тот же create_task, чтобы это ожидание не мешало работе бота
не подскажиье как это сделать?
вы наверное не так поняли, завершения данной функции не будет, там while 1. что выходит что функция будет бесконечно обновлять проверку мою, она никак не выйдет. если я что то не так понял, пришлите код
loop_in_executor можно точно так же завернуть в while 1, например
Но лучше всё-таки покажите код своей проверки, что-то я на 99% подозреваю, что там на самом деле можно всё сделать асинхронным
весь код к сожалению не могу показать, покажу главную часть
while 1:
while 1:
for i in range(10):
r = requests.get
for t in range(20):
if(...):
await bot.send_message(...)
Зачем использовать синхронный requests, если существуют асинхронные aiohttp и httpx
Код всё время парсит страницу и проверяет по наличию элемента если в кратце
17:05
Это можно делать асинхронно без отдельного потока
@andreymal а разве асинхрон запросы помогут в том чтобы в проверке отсылался мсдж с бота?
Если не создавать отдельный поток с отдельным event loop'ом, то все проблемы с отправкой сообщений автоматически исчезнут
и бот не будет занят? и тогда и будет работать сам бот у других пользователей?
Будет, если асинхронная проверка будет запущена в отдельном task'е через create_task
не мог ли бы пожалуйста скинуть код?
17:14
async def check_loop():
    async with httpx.AsyncClient() as client:
        while 1:
            r = await client.get(ссылка)
            html = r.text
            # Где-то здесь парсим страницу как обычно
            if ...:
                await bot.send_message(...)

            # Задержка полминуты между проверками,
            # чтобы лишнюю нагрузку не создавать
            await asyncio.sleep(30)

async def on_startup(dp):
    # В переменной check_loop будет храниться
    # созданный объект Task, через который можно
17:26
Однако у такого подхода есть проблема — нет никакой обработки ошибок, и если при проверке возникнет ошибка, то проверка остановится, а ошибка безвозвратно потеряется в никуда. Поэтому лучше непосредственно работу по проверке вынести в отдельную функцию, а ошибки перехватывать через try-except и уведомлять о них, примерно так:
async def check():
    async with httpx.AsyncClient() as client:
        r = await client.get(ссылка)
        html = r.text
        # Где-то здесь парсим страницу как обычно
        if ...:
            await bot.send_message(...)


async def check_loop():
    while 1:
        try:
            await check()
        except Exception:
            traceback.print_exc()
            await bot.send_message(АДМИН_МНЕ_ПОПЛОХЕЛО)

        await asyncio.sleep(30)

async def on_startup(dp):
    check_task = asyncio.create_task(check_loop())
Всё равно так же. Утверждаю, у меня в функции два for, они длятся не быстро, и соответственно между ними даже asyncio.sleep не поможет, здесь нужно решать проблему только с отправкой через бота
Что такого тяжёлого делают эти два for?
Он парсит сначала с первого, 10 страниц, поочереди, потом на каждой странице по компонентам страницу, а дальше проверки, по которым дальше и отсылаются сообщения через телеграм бота
К сожалению никак не смогу убрать столь большую проверку
@AndreyLaki Каждая страница запрашивается через await client.get, между страницами небольшая пауза через asyncio.sleep — в вашем описании нет ничего, что могло бы помешать работе асинхронного бота
@AndreyLaki Когда я делал всякие разные парсинги страниц, синхронная работа у меня занимала сотые доли секунды — недостаточно для того, чтобы бот заблокировался. Или вы написали прям какой-то очень-очень ужасный код парсинга, или вы просто ещё не научились писать асинхронный код
Хах, простите, забыл про второй requests, Исправил на httpx и всё теперь хорошо. Большое спасибо за помощь, благодарен вам!

last day (15 days later) »