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
相关产品推荐
相关产品推荐

