Discord音乐机器人填写TokenID触发Cannot close a running event loop错误
错误成因分析
该RuntimeError: Cannot close a running event loop错误的触发原因主要有3类:
- 运行环境冲突:如果你在Jupyter Notebook、IPython交互式解释器这类自带常驻事件循环的环境中运行代码,discord.py的
client.run()方法尝试关闭已有循环时就会触发报错。 - 同步代码阻塞事件循环:你代码中使用的
youtube_dl是同步库,ydl.extract_info执行时会阻塞discord.py的异步事件循环,导致循环状态异常,无法正常关闭。 - discord.py版本不兼容:你参考的教程基于discord.py v1.x版本编写,v2.x版本后
add_cog改为异步方法,旧的同步注册cog逻辑会导致事件循环状态异常。
解决方案
你可以按照优先级尝试以下修复方案:
- 更换运行环境:直接使用系统原生Python解释器运行脚本,在终端执行
python 你的主脚本文件名.py即可,不要在自带事件循环的交互式环境中运行。 - 替换同步依赖并优化阻塞逻辑:首先安装异步兼容的
yt-dlp替代已停止维护的youtube_dl,执行命令:pip install yt-dlp,之后修改play方法将同步调用放到线程池执行,避免阻塞事件循环:
# 首先修改music.py的导入 import asyncio import yt_dlp as youtube_dl # play方法修改后代码如下 @commands.command() async def play(self,ctx,url): ctx.voice_client.stop() FFMPEG_OPTIONS = {'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options':'-vn'} YDL_OPTIONS = {'format':"bestaudio"} vc = ctx.voice_client with youtube_dl.YoutubeDL(YDL_OPTIONS) as ydl: info = await asyncio.to_thread(ydl.extract_info, url, download=False) url2 = info['formats'][0]['url'] source = await discord.FFmpegOpusAudio.from_probe(url2,**FFMPEG_OPTIONS) vc.play(source)
- 适配discord.py v2.x的异步启动逻辑:将主文件的启动逻辑改为异步写法,同时修改cog注册方式:
# 主文件代码修改后如下 import discord from discord.ext import commands import asyncio client = commands.Bot(command_prefix='-', intents = discord.Intents.all()) async def main(): async with client: await client.load_extension('music') await client.start('你的实际Bot TOKEN') asyncio.run(main())
同时修改music.py中的setup函数为异步版本:
async def setup(client): await client.add_cog(music(client))
- 临时修复方案:如果仅需要本地快速测试,可以在
client.run()执行前添加如下代码强制清理已有事件循环:
import asyncio try: asyncio.get_running_loop().stop() except RuntimeError: pass # 之后再执行client.run('TOKEN')
内容的提问来源于stack exchange,提问作者Prab-mat
相关产品推荐
相关产品推荐

