-
Notifications
You must be signed in to change notification settings - Fork 6k
Description
Issue I am facing
I need to keep a persistet aiohttp session, which I try to store inside bot_data and, given it should only be created in async context, I have an async function wrapper around session and application creation. So I need to launch the bot inside an already existing async context, hence, running event loop. I've referred to #3310, #3711 and wiki on running with other asyncio FWs. I've understood the following points:
- To launch application in an already running event loop I need to stop using
Application.run_pollingand stick with the sequence of calls it replaces (Application.initalize -> Application.start -> Application.updater.start_polling -> Application.updater.stop -> Application.stop -> Application.shutdown) - First and last calls can be replaced with a context manager (
with application) making shortening call sequence toApplication.start -> Application.updater.start_polling -> Application.updater.stop -> Application.stop - Between
start_pollingandupdater.stopshould be something that would keep the event loop alive to prevent application fom stopping immediately after starting
So I came up with the code below, which for some reason doesn't quit upon Ctrl-C event. Moreover, it takes 2 Ctrl-Cs to stop the program, and the second produces the stacktrace below. And my question is, how to correctly handle termination when running inside already existing event loop?
Traceback to the issue
Traceback (most recent call last):
File "/usr/lib/python3.9/asyncio/runners.py", line 44, in run
return loop.run_until_complete(main)
File "/usr/lib/python3.9/asyncio/base_events.py", line 629, in run_until_complete
self.run_forever()
File "/usr/lib/python3.9/asyncio/base_events.py", line 596, in run_forever
self._run_once()
File "/usr/lib/python3.9/asyncio/base_events.py", line 1854, in _run_once
event_list = self._selector.select(timeout)
File "/usr/lib/python3.9/selectors.py", line 452, in select
def select(self, timeout=None):
File "/home/egor/.vscode-server/extensions/ms-python.debugpy-2024.0.0-linux-arm64/bundled/libs/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_trace_dispatch_regular.py", line 374, in __call__
return None if event == 'call' else NO_FTRACE
KeyboardInterrupt
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3.9/runpy.py", line 197, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/usr/lib/python3.9/runpy.py", line 87, in _run_code
exec(code, run_globals)
File "/home/egor/.vscode-server/extensions/ms-python.debugpy-2024.0.0-linux-arm64/bundled/libs/debugpy/adapter/../../debugpy/launcher/../../debugpy/__main__.py", line 39, in <module>
cli.main()
File "/home/egor/.vscode-server/extensions/ms-python.debugpy-2024.0.0-linux-arm64/bundled/libs/debugpy/adapter/../../debugpy/launcher/../../debugpy/../debugpy/server/cli.py", line 430, in main
run()
File "/home/egor/.vscode-server/extensions/ms-python.debugpy-2024.0.0-linux-arm64/bundled/libs/debugpy/adapter/../../debugpy/launcher/../../debugpy/../debugpy/server/cli.py", line 284, in run_file
runpy.run_path(target, run_name="__main__")
File "/home/egor/.vscode-server/extensions/ms-python.debugpy-2024.0.0-linux-arm64/bundled/libs/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_runpy.py", line 321, in run_path
return _run_module_code(code, init_globals, run_name,
File "/home/egor/.vscode-server/extensions/ms-python.debugpy-2024.0.0-linux-arm64/bundled/libs/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_runpy.py", line 135, in _run_module_code
_run_code(code, mod_globals, init_globals,
File "/home/egor/.vscode-server/extensions/ms-python.debugpy-2024.0.0-linux-arm64/bundled/libs/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_runpy.py", line 124, in _run_code
exec(code, run_globals)
File "/home/egor/dev/python/misc/bot_scripts/bot_for_gpt.py", line 67, in <module>
asyncio.run(main())
File "/usr/lib/python3.9/asyncio/runners.py", line 47, in run
_cancel_all_tasks(loop)
File "/usr/lib/python3.9/asyncio/runners.py", line 63, in _cancel_all_tasks
loop.run_until_complete(
File "/usr/lib/python3.9/asyncio/base_events.py", line 629, in run_until_complete
self.run_forever()
File "/usr/lib/python3.9/asyncio/base_events.py", line 596, in run_forever
self._run_once()
File "/usr/lib/python3.9/asyncio/base_events.py", line 1854, in _run_once
event_list = self._selector.select(timeout)
File "/usr/lib/python3.9/selectors.py", line 469, in select
fd_event_list = self._selector.poll(timeout, max_ev)
KeyboardInterrupt
2024-02-22 11:46:07,802 - asyncio - ERROR - Task exception was never retrieved
future: <Task finished name='Task-1' coro=<main() done, defined at /home/egor/dev/python/misc/bot_scripts/bot_for_gpt.py:42> exception=RuntimeError('This Application is still running!')>
Traceback (most recent call last):
File "/home/egor/dev/python/misc/bot_scripts/bot_for_gpt.py", line 60, in main
await asyncio.sleep(0)
File "/usr/lib/python3.9/asyncio/tasks.py", line 639, in sleep
await __sleep0()
File "/usr/lib/python3.9/asyncio/tasks.py", line 633, in __sleep0
yield
asyncio.exceptions.CancelledError
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/egor/dev/python/misc/bot_scripts/bot_for_gpt.py", line 60, in main
await asyncio.sleep(0)
File "/home/egor/dev/python/misc/bot_scripts/.env/lib/python3.9/site-packages/telegram/ext/_application.py", line 393, in __aexit__
await self.shutdown()
File "/home/egor/dev/python/misc/bot_scripts/.env/lib/python3.9/site-packages/telegram/ext/_application.py", line 542, in shutdown
raise RuntimeError("This Application is still running!")
RuntimeError: This Application is still running!
2024-02-22 11:46:07,806 - asyncio - ERROR - Task was destroyed but it is pending!
task: <Task pending name='Application:XXXXXXXXXX:update_fetcher' coro=<Application._update_fetcher() running at /home/egor/dev/python/misc/bot_scripts/.env/lib/python3.9/site-packages/telegram/ext/_application.py:1179> wait_for=<Future pending cb=[<TaskWakeupMethWrapper object at 0x7f90e80430>()]> cb=[gather.<locals>._done_callback() at /usr/lib/python3.9/asyncio/tasks.py:764]>
Exception ignored in: <coroutine object Application._update_fetcher at 0x7f91791c40>
Traceback (most recent call last):
File "/home/egor/dev/python/misc/bot_scripts/.env/lib/python3.9/site-packages/telegram/ext/_application.py", line 1179, in _update_fetcher
File "/usr/lib/python3.9/asyncio/queues.py", line 168, in get
File "/usr/lib/python3.9/asyncio/base_events.py", line 746, in call_soon
File "/usr/lib/python3.9/asyncio/base_events.py", line 510, in _check_closed
RuntimeError: Event loop is closedRelated part of your code
import aiohttp
import asyncio
import logging
from telegram import Update
from telegram.ext import ApplicationBuilder, CommandHandler, ContextTypes
from creds import BOT_TOKEN
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
await context.bot.send_message(chat_id=update.effective_chat.id, text="How can I help you?")
async def main():
async with aiohttp.ClientSession() as aiohttp_session:
application = ApplicationBuilder().token(BOT_TOKEN).build()
application.bot_data['aiohttp_session'] = aiohttp_session
start_handler = CommandHandler('start', start)
application.add_handler(start_handler)
async with application:
await application.start()
await application.updater.start_polling(timeout=30)
try:
while True: # THIS IS SUPPOSED TO KEEP EVENT LOOP RUNNING UNTIL CTRL-C
await asyncio.sleep(0)
except KeyboardInterrupt:
await application.updater.stop()
await application.stop()
if __name__ == '__main__':
asyncio.run(main())Operating System
Raspberry Pi OS (based on debian 11 bullseye)
Version of Python, python-telegram-bot & dependencies
python-telegram-bot 20.8
Bot API 7.0
Python 3.9.2 (default, Feb 28 2021, 17:03:44) [GCC 10.2.1 20210110]