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

Discord.py机器人无法优雅关闭,调用bot.close()触发Event loop is closed错误

Discord.py机器人无法优雅关闭,调用bot.close()触发Event loop is closed错误

我完全理解你想要程序干净无报错的心情,这个问题在Python 3.8+的Windows环境下挺常见的——主要是因为默认使用的ProactorEventLoop在Bot关闭后,还有一些底层的管道传输对象在垃圾回收时,试图访问已经关闭的事件循环,从而抛出这个“Event loop is closed”的错误。

先看你的简化代码,问题出在bot.run()的自动事件循环管理逻辑上,结合Windows环境的事件循环特性,就导致了这个残留的报错。下面给你几个可行的解决办法:

方法一:切换到Selector事件循环

在代码开头手动设置使用WindowsSelectorEventLoopPolicy,避开Proactor事件循环的遗留问题:

import discord
from discord.ext import commands
import os
from dotenv import load_dotenv
import asyncio

# 新增这行,切换事件循环策略
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())

TOKEN = os.getenv('TOKEN')

intents = discord.Intents.default()
bot = commands.Bot(command_prefix='!', intents=intents)


@bot.event
async def on_ready():
    print(f'Logged in as {bot.user}!')

    await asyncio.sleep(5)

    print("shutting down")
    await bot.close()


bot.run(TOKEN)

方法二:手动管理事件循环与Bot生命周期

放弃使用bot.run(),改用async with来管理Bot的上下文,这样能更精准地控制启动和关闭流程,避免自动循环管理的遗留问题:

import discord
from discord.ext import commands
import os
from dotenv import load_dotenv
import asyncio

load_dotenv()
TOKEN = os.getenv('TOKEN')

intents = discord.Intents.default()
bot = commands.Bot(command_prefix='!', intents=intents)


@bot.event
async def on_ready():
    print(f'Logged in as {bot.user}!')
    await asyncio.sleep(5)
    print("shutting down")
    await bot.close()


async def main():
    async with bot:
        await bot.start(TOKEN)

asyncio.run(main())

方法三:临时屏蔽特定错误(不推荐,仅应急用)

如果你暂时不想调整代码结构,可以通过重写底层方法来忽略这个特定错误,但这只是治标不治本的应急方案:

import sys
from asyncio.proactor_events import _ProactorBasePipeTransport

# 重写__del__方法,过滤掉事件循环关闭的错误
def silence_event_loop_closed(func):
    def wrapper(self, *args, **kwargs):
        try:
            return func(self, *args, **kwargs)
        except RuntimeError as e:
            if str(e) != "Event loop is closed":
                raise
    return wrapper

_ProactorBasePipeTransport.__del__ = silence_event_loop_closed(_ProactorBasePipeTransport.__del__)

# 以下是你的原代码
import discord
from discord.ext import commands
import os
from dotenv import load_dotenv
import asyncio

TOKEN = os.getenv('TOKEN')

intents = discord.Intents.default()
bot = commands.Bot(command_prefix='!', intents=intents)


@bot.event
async def on_ready():
    print(f'Logged in as {bot.user}!')

    await asyncio.sleep(5)

    print("shutting down")
    await bot.close()


bot.run(TOKEN)

优先推荐方法一或方法二,这两个方案能从根源上解决问题,让你的Bot真正实现优雅关闭。

备注:内容来源于stack exchange,提问作者Duck Lord

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 11:38:00