Python异步WebSocket Bot的RuntimeError与RuntimeWarnings处理问题
问题分析与修复方案
错误根源拆解
- 后台任务未被跟踪/取消:你用
asyncio.create_task创建的WebSocket监听任务没有保存引用,Bot关闭时无法终止这个无限循环的任务,导致事件循环一直处于运行状态,触发RuntimeError: Cannot close a running event loop。 - Polling调用与事件循环冲突:
application.run_polling()内部会接管事件循环的生命周期管理,退出时可能未正确释放资源,导致后续的shutdown调用在仍运行的循环中执行。 - 潜在的协程调度问题:如果
main函数未通过标准方式启动(比如asyncio.run),或异常场景下initialize/shutdown的await逻辑被跳过,就会出现协程未等待的警告。
修复后的完整代码
import asyncio from telegram import Bot from telegram.ext import Application import websockets async def send_notification_to_chat(bot, message, chat_id): try: await bot.send_message(chat_id=chat_id, text=message) print("Message sent successfully.") except Exception as e: print(f"Failed to send message: {str(e)}") async def logs_Tokens(callback, bot, chat_id): uri = "wss://your-websocket-uri" while True: try: async with websockets.connect(uri) as websocket: print("Connected to WebSocket server") while True: message = await websocket.recv() # 此处添加你的消息处理逻辑 await callback(bot, "Token activity detected!", chat_id) except websockets.exceptions.ConnectionClosed: print("WebSocket connection closed, reconnecting...") await asyncio.sleep(5) # 重连前等待避免频繁重试 except Exception as e: print(f"WebSocket error: {str(e)}") await asyncio.sleep(5) async def main(): bot = Bot(token="your-token-here") application = Application.builder().bot(bot).build() chat_id = "chat_number" # 保存后台任务引用,方便后续取消 ws_task = asyncio.create_task(logs_Tokens(send_notification_to_chat, bot, chat_id)) try: await application.initialize() # 改用start_polling + wait_stop,替代run_polling,更灵活控制循环生命周期 await application.start_polling() await application.updater.wait_stop() finally: # 主动取消WebSocket后台任务 ws_task.cancel() try: await ws_task except asyncio.CancelledError: print("WebSocket task cancelled successfully") # 确保应用资源正常释放 await application.shutdown() if __name__ == "__main__": # 用标准方式启动异步主函数 asyncio.run(main())
关键修改说明
- 移除多余lambda包装:
send_notification_to_chat本身是异步函数,直接传入即可,无需额外lambda包装。 - 跟踪并取消后台任务:保存
ws_task引用,在finally块中主动取消并等待任务结束,确保事件循环能正常退出。 - 调整Polling调用逻辑:用
start_polling+wait_stop替代run_polling,避免内部循环管理冲突,更清晰控制Bot的启动与停止。 - 添加WebSocket异常处理:处理连接关闭等异常,避免任务意外崩溃,同时添加重连等待逻辑,提升稳定性。
效果验证
修改后:
- 后台WebSocket任务会在Bot关闭时被正确终止,事件循环可正常退出,解决
Cannot close a running event loop错误。 initialize和shutdown协程都会被正确await,消除未等待的警告。- Bot可正常初始化、处理WebSocket消息,并在收到停止信号时优雅关闭。
内容的提问来源于stack exchange,提问作者David
相关产品推荐
相关产品推荐

