Python-telegram-bot从v13升级到v20后出现事件循环相关RuntimeError问题求助
兄弟我太懂你升级PTB版本后踩坑的痛苦了!从v13的同步写法转到v20全异步架构,确实很容易碰到事件循环的冲突问题。看你贴的报错和代码,我几乎能肯定——你是不是在Jupyter Notebook/IPython这类自带事件循环的环境里跑代码啊?
问题原因分析
v20版本的python-telegram-bot完全采用异步设计,当你调用application.run_polling()时,它默认会尝试创建并启动一个新的事件循环。但如果你是在Notebook或者IPython终端里运行,这些环境本身就已经启动了一个事件循环在后台跑着,这时候PTB再想启动新循环就会触发RuntimeError: This event loop is already running;后续程序尝试关闭循环时,又因为循环本来就在运行,所以又会报RuntimeError: Cannot close a running event loop。
另外顺便提一句,你代码里还有两个小拼写错误,虽然不是事件循环问题,但会导致/start命令执行失败:
- 日志格式里的
$(asctime)s应该改成%(asctime)s(把$换成%) send_messsage多写了一个s,应该是send_message
解决方案
方案1:最稳妥——换普通Python环境运行
把代码保存成.py文件(比如my_bot.py),然后打开终端,切换到你的conda环境working_env,用python my_bot.py命令运行,不要在Notebook里跑。这种方式下PTB会自己管理事件循环,不会有冲突问题。
方案2:如果必须在Notebook/IPython里运行
那就让PTB复用环境已经存在的事件循环,修改代码如下:
import logging import asyncio from telegram import Update from telegram.ext import ApplicationBuilder, ContextTypes, CommandHandler mytoken = 'here_my_token' logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO ) async def start(update: Update, context: ContextTypes.DEFAULT_TYPE): await context.bot.send_message(chat_id=update.effective_chat.id, text="Welcome to my bot, please say something!") if __name__ == '__main__': application = ApplicationBuilder().token(mytoken).build() start_handler = CommandHandler('start', start) application.add_handler(start_handler) # 复用已有的事件循环 try: loop = asyncio.get_running_loop() application.run_polling(loop=loop) except RuntimeError: # 如果当前没有运行中的循环,就正常启动 application.run_polling()
另外注意:在Notebook里每次重新运行代码前,最好先关闭之前的bot实例,不然也可能残留进程导致冲突,可以在代码开头加一段清理逻辑:
# 清理可能残留的bot实例 try: await application.shutdown() except NameError: # 如果application还没定义就跳过 pass
最后再提醒下
v20和v13的API变化挺大的,除了事件循环,还要注意其他异步相关的写法,比如所有和bot交互的方法都要加await,handler函数必须是async def定义的,这些你已经做对了,继续保持就行~
备注:内容来源于stack exchange,提问作者bbaa

