如何无异常关闭Discord Client连接?
正确关闭Discord Client连接以避免"Event loop is closed"异常
问题场景
运行以下Discord Client代码:
import os import discord from dotenv import load_dotenv load_dotenv() intents = discord.Intents.default() TOKEN = os.getenv('DISCORD_TOKEN') GUILD = os.getenv('DISCORD_GUILD') client = discord.Client(intents=intents) @client.event async def on_ready(): guild = None for guild in client.guilds: if guild.name == GUILD: break print( f'{client.user} is connected to guild {guild.name} (id: {guild.id})' ) client.run(TOKEN)
停止程序时会抛出以下异常:
Traceback (most recent call last): File "C:\Users\HP\AppData\Local\Programs\Python\Python39\lib\asyncio\proactor_events.py", line 116, in __del__ self.close() File "C:\Users\HP\AppData\Local\Programs\Python\Python39\lib\asyncio\proactor_events.py", line 108, in close self._loop.call_soon(self._call_connection_lost, None) File "C:\Users\HP\AppData\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 751, in call_soon self._check_closed() File "C:\Users\HP\AppData\Local\Programs\Python\Python39\lib\asyncio\base_events.py", line 515, in _check_closed raise RuntimeError('Event loop is closed') RuntimeError: Event loop is closed Process finished with exit code 0
该异常不影响功能,但会干扰日志输出,需要正确断开连接以消除它。
解决方案
方法1:手动控制事件循环与优雅关闭
client.run()是阻塞方法,自动管理事件循环时可能因提前终止引发异常。改用手动启动事件循环,通过上下文管理器规范生命周期:
import os import asyncio import discord from dotenv import load_dotenv load_dotenv() intents = discord.Intents.default() TOKEN = os.getenv('DISCORD_TOKEN') GUILD = os.getenv('DISCORD_GUILD') client = discord.Client(intents=intents) @client.event async def on_ready(): guild = next((g for g in client.guilds if g.name == GUILD), None) if guild: print(f'{client.user} is connected to guild {guild.name} (id: {guild.id})') async def main(): async with client: await client.start(TOKEN) if __name__ == "__main__": try: asyncio.run(main()) except KeyboardInterrupt: # 捕获Ctrl+C中断,确保连接优雅关闭 pass
async with client会自动调用client.close(),配合asyncio.run()能避免循环提前关闭的问题。
方法2:捕获特定异常忽略(快速处理)
如果不想修改启动逻辑,直接过滤该垃圾回收阶段触发的异常:
import os import discord from dotenv import load_dotenv load_dotenv() intents = discord.Intents.default() TOKEN = os.getenv('DISCORD_TOKEN') GUILD = os.getenv('DISCORD_GUILD') client = discord.Client(intents=intents) @client.event async def on_ready(): guild = None for guild in client.guilds: if guild.name == GUILD: break print( f'{client.user} is connected to guild {guild.name} (id: {guild.id})' ) if __name__ == "__main__": try: client.run(TOKEN) except RuntimeError as e: if str(e) == "Event loop is closed": # 忽略该特定异常 pass
方法3:主动触发优雅关闭
如果需要主动关闭(比如通过指令触发),可在事件或命令中调用client.close():
# 示例:添加关闭事件处理 @client.event async def on_disconnect(): # 可选:添加关闭前的清理逻辑 await client.close() # 示例:在命令中触发关闭(需配合命令扩展) @client.command() async def shutdown(ctx): await ctx.send("正在关闭连接...") await client.close()
内容的提问来源于stack exchange,提问作者ColorfulYoshi
相关产品推荐
相关产品推荐

