-
Issue I am facingI have a bot with an infinite background job. What is the best, "canonical" way of stopping/quitting the bot in this case (with saving the state to a persistent storage and other stuff that Application.stop() does). Ideally, it should work not only when I press ctrl-c but in any scenario when the bot stops (for example, when an exception that could not be handled for some reason was raised and the bot stopped). Traceback to the issueNo response Related part of your codeclass Bot:
def init(self, app: Application) -> None:
self.app = app
self.app.job_queue.run_once(
callback=self.infinite_task,
when=0
)
async def infinite_task(self) -> None:
while True:
print("I'm a bot")
await asyncio.sleep(1)
application = ApplicationBuilder().token('TOKEN').build()
Bot(application)
application.run_polling() Operating SystemDebian 10 Version of Python, python-telegram-bot & dependenciespython-telegram-bot 20.0a2
Bot API 6.1
Python 3.7.3 (default, Jan 22 2021, 20:04:44) [GCC 8.3.0] |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 1 reply
-
As a first step I would try to get rid of the infinite loop. Those should be reserved to very few critical tasks like polling for updates or so. Alternatives can include e.g. using infinite_tasks = []
async def post_init(app):
infinite_tasks.append(asyncio.create_task(infinite_task()))
...
app.run_polling(close_loop=False)
for task in infinite_tasks:
task.cancel() (Haven't tested the code) Or use |
Beta Was this translation helpful? Give feedback.
-
|
Beta Was this translation helpful? Give feedback.
-
@oratosquilla-oratoria there is telegram.ext.Application.running. If you would explain your use case, one could probably help you better 😉 |
Beta Was this translation helpful? Give feedback.
-
I got notified that this topic is still alive :) For anyone who might stumble upon this question, that's what we use at the moment (main parts): class QueueConsumer:
def __init__(self, bot, ...):
self.bot = bot
self.connection = None
self.consumer_lock = None
async def process_message(self, msg):
await self.bot.send_message(msg)
async def run_consumer(self):
self.connection = await subscribe(on_message=self.process_message, ...)
self.consumer_lock = asyncio.Future()
await self.consumer_lock
async def signal_handler(self):
if self.connection is not None:
await self.connection.close()
if self.consumer_lock is not None:
self.consumer_lock.set_result(True)
def register_signal_handlers(self):
loop = asyncio.get_event_loop()
sigs = [signal.SIGINT, signal.SIGTERM, signal.SIGQUIT, signal.SIGABRT]
for sig in sigs:
loop.add_signal_handler(sig, lambda: asyncio.create_task(self._signal_handler()))
async def __aenter__(self):
self.register_signal_handlers()
return self
async def __aexit__(self, *args: Any):
pass
application = ApplicationBuilder().token(token).build()
async with application:
await application.initialize()
await application.start()
await application.updater.start_webhook(...)
async with QueueConsumer(application.bot, ...) as c:
await c.run_consumer()
await application.updater.stop()
await application.stop() It's a simple bot that takes messages from a queue (RabbitMQ) and resend them to the users subscribed to the bot. I'm sure the code is not perfect and can take a bit of improvement but it's been working with no problem for months (maybe even years, actually) already. |
Beta Was this translation helpful? Give feedback.
I got notified that this topic is still alive :) For anyone who might stumble upon this question, that's what we use at the moment (main parts):