You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何无异常关闭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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 00:10:13