如何在独立线程运行python-telegram-bot?解决无事件循环报错
独立线程运行Telegram Bot报错解决方案
问题场景
需要在独立线程中运行Telegram Bot以释放主线程,但运行代码时触发RuntimeError: There is no current event loop in thread 'Thread-1'错误。
原测试代码
bot_thread.py
import logging import asyncio from telegram import Update from telegram.ext import Application, ContextTypes, CommandHandler from threading import Thread from multiprocessing import Process logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO ) class Bot(Thread): async def start_msg(self, update: Update, context: ContextTypes.DEFAULT_TYPE): await context.bot.send_message(chat_id=update.effective_chat.id, text="I'm a bot, please talk to me!") def run(self): async def hello(update: Update, context: ContextTypes.DEFAULT_TYPE): await context.bot.send_message(chat_id=update.effective_chat.id, text="Starting bot") key = open('../data/keys', 'r').read() application = Application.builder().token(key).build() job_queue = application.job_queue job_queue.run_once(hello, 90) start_handler = CommandHandler('start', self.start_msg) application.add_handler(start_handler) application.run_polling()
bot.py
from bot_thread import Bot Bot().start()
完整报错信息
> python .\bot_wrapper.py 2024-05-09 15:04:13,916 - apscheduler.scheduler - INFO - Adding job tentatively -- it will be properly scheduled when the scheduler starts Exception in thread Thread-1: Traceback (most recent call last): File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2032.0_x64__qbz5n2kfra8p0\Lib\threading.py", line 1045, in _bootstrap_inner self.run() File "bot_thread.py", line 32, in run application.run_polling() File "AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\telegram\ext\_application.py", line 838, in run_polling return self.__run( ^^^^^^^^^^^ File "AppData\Local\Packages\PythonSoftwareFoundation.Python.3.11_qbz5n2kfra8p0\LocalCache\local-packages\Python311\site-packages\telegram\ext\_application.py", line 1020, in __run loop = asyncio.get_event_loop() ^^^^^^^^^^^^^^^^^^^^^^^^ File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2032.0_x64__qbz5n2kfra8p0\Lib\asyncio\events.py", line 677, in get_event_loop raise RuntimeError('There is no current event loop in thread %r.' RuntimeError: There is no current event loop in thread 'Thread-1'. C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.11_3.11.2032.0_x64__qbz5n2kfra8p0\Lib\threading.py:1047: RuntimeWarning: coroutine 'Updater.start_polling' was never awaited self._invoke_excepthook(self) RuntimeWarning: Enable tracemalloc to get the object allocation traceback
错误原因
Python的asyncio事件循环默认仅在主线程中自动创建,手动启动的子线程不会生成默认事件循环。而Telegram Bot的run_polling()方法依赖asyncio事件循环,因此在子线程中直接调用会触发找不到事件循环的错误。另外原代码中hello函数的参数不符合job_queue回调要求,会导致额外异常。
修复方案
在子线程的run()方法中手动创建并设置asyncio事件循环,将Bot的异步逻辑封装到单独的协程函数中,再通过事件循环运行。同时修正job_queue回调函数的参数格式。
修复后的bot_thread.py
import logging import asyncio from telegram import Update from telegram.ext import Application, ContextTypes, CommandHandler from threading import Thread logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO ) class Bot(Thread): async def start_msg(self, update: Update, context: ContextTypes.DEFAULT_TYPE): await context.bot.send_message(chat_id=update.effective_chat.id, text="I'm a bot, please talk to me!") async def run_bot(self): # 修正job_queue回调参数:仅接收Context参数 async def hello(context: ContextTypes.DEFAULT_TYPE): # 此处需替换为你的测试聊天ID,或调整逻辑获取目标chat_id await context.bot.send_message(chat_id="你的测试ChatID", text="Starting bot") key = open('../data/keys', 'r').read() application = Application.builder().token(key).build() start_handler = CommandHandler('start', self.start_msg) application.add_handler(start_handler) # 启动job_queue并添加任务 await application.job_queue.start() application.job_queue.run_once(hello, 90) # 运行polling await application.run_polling() def run(self): # 子线程手动创建并设置事件循环 loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) try: loop.run_until_complete(self.run_bot()) finally: loop.close()
内容的提问来源于stack exchange,提问作者DevBush
相关产品推荐
相关产品推荐

