eternnoir / pyTelegramBotAPI

Python Telegram bot api.
GNU General Public License v2.0
8.01k stars 2.02k forks source link

The need for stop_polling in async version #2386

Open EugeneNeuron opened 1 month ago

EugeneNeuron commented 1 month ago
  1. What version of pyTelegramBotAPI are you using? 4.22.0
  2. What OS are you using? Gnu/Linux
  3. What version of python are you using? 3.10.7

I see how to gracefully stop polling using TeleBot class (#2098), but how to properly stop bot/polling using AsyncTeleBot? I tried AsyncTeleBot.close_session, but it gives an error.

ERROR Aiohttp ClientError: ClientOSError
ERROR Unhandled exception (full traceback for debug level): Request timeout. Request: method=get url=getUpdates params=<aiohttp.formdata.FormData object at 0x7fb62f4137c0> files=None request_timeout=300

I can catch it and handle myself, but maybe there's a better way?

coder2020official commented 1 month ago

u close session first then stop polling

FaridMalekpour commented 3 weeks ago

To gracefully stop polling when using AsyncTeleBot in pyTelegramBotAPI, you can use the stop_polling() method in combination with await to ensure that the bot's polling is properly stopped. Since AsyncTeleBot runs asynchronously, the close_session() method will close the bot's session but might not ensure proper cleanup of all resources if not handled correctly. Here's how you can gracefully stop the bot using AsyncTeleBot:

import asyncio
from telebot.async_telebot import AsyncTeleBot

API_TOKEN = 'YOUR_BOT_API_TOKEN'
bot = AsyncTeleBot(API_TOKEN)

# Start polling
async def start_polling():
    await bot.polling(non_stop=True)

# Gracefully stop polling
async def stop_polling():
    await bot.stop_polling()  # This will stop the polling process
    await bot.close_session()  # Close the bot's aiohttp session

async def main():
    try:
        await start_polling()
    except (KeyboardInterrupt, SystemExit):
        print("Gracefully stopping the bot...")
        await stop_polling()

if __name__ == '__main__':
    asyncio.run(main())
EugeneNeuron commented 2 weeks ago

Thank you @coder2020official and @FaridMalekpour for your answers.

But, sorry, maybe I don't understand something, but there's literally no such method as stop_polling for AsyncTeleBot.

In [7]: bot = AsyncTeleBot(token)

In [9]: bot.stop_polling()
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In [9], line 1
----> 1 bot.stop_polling()

AttributeError: 'AsyncTeleBot' object has no attribute 'stop_polling'
coder2020official commented 2 weeks ago

Hi, yes, I am currently working on this, hence this issue is still open. Will notify you when PR is ready

coder2020official commented 2 weeks ago

You may try my PR version out if you want. It should introduce(I hope) graceful & proper shutdown of polling.

EugeneNeuron commented 2 weeks ago

Hi @coder2020official,

I tried you patch and it worked for me like a charm.

I tried both the way @FaridMalekpour suggested and from inside the message_handler, like this:


        @self.bot.message_handler(commands=['stop_bot'])
        async def handle_stop_bot(message: Message):
            if message.from_user.id == self.admin:
                await self.bot.send_message(
                    message.chat.id,
                    "Bot is now shutting down gracefully."
                )
                await self.bot.stop_polling()