如何修复Discord音乐机器人的命令执行报错问题
错误原因分析
KeyError: 'For':你在代码中直接修改了用于索引播放列表的原文件名变量,将原键名Foriegn_Accent.wav做了替换下划线+截取前3位的操作,得到字符串For后再去playlist字典中查询,字典中不存在该键,直接抛出索引异常,程序中断运行。TimeoutError:discord.py是异步框架,你使用同步阻塞的time.sleep()会卡死整个事件循环,导致机器人无法向Discord服务器发送心跳包、响应其他事件,超过平台超时限制后就会抛出超时错误,强制断开连接。同时voice.play()本身是非阻塞方法,调用后会在后台播放音频,同步等待的逻辑本身也不符合异步框架的运行规则。
修复方案
修改要点如下:
- 单独创建变量存储用于展示的歌曲名,不要修改用于索引
playlist的原键名,同时删掉无意义的前3位截断逻辑 - 导入asyncio库,使用异步非阻塞的
asyncio.sleep()替代time.sleep() - 保留原播放列表的索引逻辑,避免出现键不存在的问题
修改后的完整代码:
import discord from discord.ext import commands from discord import FFmpegPCMAudio import asyncio # 播放列表存储wav文件名、歌手名、歌曲时长 playlist = {'Foriegn_Accent.wav':['Plague of Grackles (aka @borlip)', 128],'Go_Harder.wav':['ac', 234]} # 设置指令前缀 client = commands.Bot(command_prefix = '/') # 机器人登录完成回调 @client.event async def on_ready(): print('The bot is now ready') print('--------------------') @client.command(pass_context = True) async def join(ctx): # 用户发送/join指令后机器人加入频道并播放音乐 channel = ctx.message.author.voice.channel voice = await channel.connect() # 加入语音频道 for song_key in playlist: # 遍历播放列表 source = FFmpegPCMAudio(song_key) # 读取音频文件 voice.play(source) # 播放音频 # 单独处理展示用的歌曲名,不修改原索引键 display_name = song_key.replace('.wav', '').replace('_', ' ') artist = playlist[song_key][0] length = playlist[song_key][1] await ctx.send(f'Playing {display_name} by {artist}') # 发送播报消息 await asyncio.sleep(length) # 异步等待歌曲播放完成,不阻塞事件循环
如果需要更稳定的播放检测逻辑,可以替换等待部分的代码,不依赖预设时长:
# 替换await asyncio.sleep(length)部分 while voice.is_playing(): await asyncio.sleep(1)
内容的提问来源于stack exchange,提问作者Anthony Ciccone
相关产品推荐
相关产品推荐

