3

i have a bot which parses some links given by user.
When clients want to parse realy huge amount of links, bot parses them, creates csv file from those links, sends it to user(user can download and view this file) and then raise TimeoutError

Cause exception while getting updates.
Traceback (most recent call last):
  File "/Users/alex26/miniforge3/envs/rq/lib/python3.8/site-packages/aiogram/dispatcher/dispatcher.py", line 381, in start_polling
    updates = await self.bot.get_updates(
  File "/Users/alex26/miniforge3/envs/rq/lib/python3.8/site-packages/aiogram/bot/bot.py", line 110, in get_updates
    result = await self.request(api.Methods.GET_UPDATES, payload)
  File "/Users/alex26/miniforge3/envs/rq/lib/python3.8/site-packages/aiogram/bot/base.py", line 231, in request
    return await api.make_request(await self.get_session(), self.server, self.__token, method, data, files,
  File "/Users/alex26/miniforge3/envs/rq/lib/python3.8/site-packages/aiogram/bot/api.py", line 139, in make_request
    async with session.post(url, data=req, **kwargs) as response:
  File "/Users/alex26/miniforge3/envs/rq/lib/python3.8/site-packages/aiohttp/client.py", line 1138, in __aenter__
    self._resp = await self._coro
  File "/Users/alex26/miniforge3/envs/rq/lib/python3.8/site-packages/aiohttp/client.py", line 559, in _request
    await resp.start(conn)
  File "/Users/alex26/miniforge3/envs/rq/lib/python3.8/site-packages/aiohttp/client_reqrep.py", line 913, in start
    self._continue = None
  File "/Users/alex26/miniforge3/envs/rq/lib/python3.8/site-packages/aiohttp/helpers.py", line 721, in __exit__
    raise asyncio.TimeoutError from None
asyncio.exceptions.TimeoutError

Some example how my bot looks like(that's not real code, that's EXAMPLE):


bot = Bot(token=API_TOKEN)
dp = Dispatcher(bot)

def parse_1000_links():
    #it takes about 10 mins and therefore that's the same like sleep(600)
    sleep(600)


@dp.message_handler()
async def msg_handler(message: types.Message):
    if msg == 'parse 1000 links':
        res = parse_1000_links()
        create_csv_from_res(res)
        file_open_obj = open('data.csv', 'rb')
        await bot.send_document(message.from_user.id, file_open_obj)
.....


if __name__ == '__main__':
    executor.start_polling(dp, skip_updates=True)

User can even get from bot this final file, but after sending this file to user, bot raises this error. That's strange. If user get message, it means that everything is fine(That's my opinion)
How to fix my issue?
Thanks

alex-uarent-alex
  • 363
  • 1
  • 10

1 Answers1

1

You should avoid using blocking operations, cause they freeze ALL event loop.

If you can't use async version of your dependency, use executor: https://docs.python.org/3/library/asyncio-eventloop.html#executing-code-in-thread-or-process-pools

Oleg
  • 523
  • 2
  • 10
  • It really helped me, but i have one more question. How long does it take for the code to work to be considered as a blocking operator? For example, are sleep(1) or sleep(10) or sleep(20) blocking operators? – alex-uarent-alex Jun 07 '22 at 15:07
  • It not depends on a time. If it's sync - it's blocking, not async – Oleg Jun 08 '22 at 13:49
  • could you tell me more about it by sharing some videos or links? I understand want you are saying, but i believe some practice and additional knowledge won't hurt. For example i have huge sync code which consists of 4 long stages. Should i create one function from it and run it through executor or should i create 4 different functions and run them one by one though executor in message handler? – alex-uarent-alex Jun 08 '22 at 18:54
  • use external workers, e.g.: celery – Oleg Jun 09 '22 at 18:12