如何解决Telethon与Telegram Bot终止时的asyncio事件循环错误?
问题定位与解决方案
核心原因分析
终止脚本时出现的RuntimeError(协程未被await、事件循环已关闭),本质是Telethon客户端的后台协程未被正确终止,且事件循环提前关闭后仍有任务在尝试执行。Telethon内部会运行多个后台协程(比如心跳、更新监听),如果直接中断脚本,这些协程会变成“悬空任务”,触发错误。
具体解决步骤
1. 显式捕获中断信号,主动关闭Telethon客户端
在脚本中捕获KeyboardInterrupt(Ctrl+C触发的中断),先调用await client.disconnect()终止Telethon的所有后台任务,再处理剩余协程。
2. 等待所有未完成协程执行完毕
关闭客户端后,用asyncio.gather收集并等待所有未完成的异步任务,避免“协程未被await”的报错。
3. 规范事件循环的生命周期管理
显式创建并管理事件循环,确保所有任务完成后再关闭循环,而非依赖asyncio.run()的自动处理(它可能在任务未完全结束时就关闭循环)。
修改后的代码示例
import asyncio from telethon import TelegramClient # 替换为你的API信息 API_ID = 123456 API_HASH = "your_api_hash" BOT_TOKEN = "your_bot_token" async def main(): # 初始化Telethon客户端 client = TelegramClient('telethon_session', API_ID, API_HASH) await client.start(bot_token=BOT_TOKEN) try: # 你的群成员获取逻辑 async for member in client.iter_participants('目标群聊ID/用户名'): print(f"成员:{member.id} - {member.first_name}") # 保持客户端运行,直到收到中断信号 await client.run_until_disconnected() except KeyboardInterrupt: print("\n正在终止脚本,关闭Telethon客户端...") # 主动断开客户端,终止后台协程 await client.disconnect() finally: # 等待所有未完成的异步任务结束 pending_tasks = asyncio.all_tasks() if pending_tasks: await asyncio.gather(*pending_tasks, return_exceptions=True) if __name__ == "__main__": loop = asyncio.get_event_loop() try: loop.run_until_complete(main()) finally: # 所有任务完成后,再关闭事件循环 loop.close()
关键细节说明
client.run_until_disconnected():Telethon提供的方法,会自动管理后台协程,直到客户端主动断开,比手动写死循环更可靠。asyncio.gather(*pending_tasks, return_exceptions=True):收集所有未完成任务,return_exceptions=True确保即使有任务报错,也不会中断整个等待流程。- 避免在未关闭Telethon客户端的情况下直接终止脚本:这会导致后台协程失去管理,触发“事件循环已关闭”的错误。
内容的提问来源于stack exchange,提问作者Jeevan Daniel Mahtani
相关产品推荐
相关产品推荐

