discord.py音乐机器人实现播放队列时触发str无play属性错误求解
错误原因
你的报错核心是self.vc被赋值为字符串类型,本身不存在play方法:
- 类初始化时你将
self.vc设置为了空字符串"" - 在
siguiente方法开头你又重复将self.vc重置为空字符串 - 全程没有将
ctx.voice_client这个语音客户端实例赋值给self.vc,调用self.vc.play必然触发属性错误
同时你的代码还存在几个逻辑错误:
siguiente方法里写了多余的for循环,会一次性尝试播放队列所有歌曲,不符合队列逐首播放的逻辑- 混用全局
queue和实例属性self.queue,多服务器使用时会出现队列冲突 is_playing是语音客户端的方法,你在判断时没有加括号,永远返回TrueFFmpegPCMAudio.from_probe是异步方法,你没有加await关键字
修复步骤
- 修改类初始化逻辑,将
self.vc初始化为None,不要用空字符串:
def __init__(self,client): self.client = client self.queue = [] # 直接用实例属性存队列,不要用全局变量 self.is_playing = False self.vc = None
- 每次连接语音频道后,将语音客户端实例绑定到
self.vc,修改play命令的连接逻辑:
if ctx.voice_client is None: await voice_channel.connect() else: await ctx.voice_client.move_to(voice_channel) self.vc = ctx.voice_client # 新增这行绑定实例
- 重写
siguiente方法,删掉错误的重置逻辑和for循环:
async def siguiente(self): if len(self.queue) > 0 and self.vc is not None and not self.vc.is_playing(): self.is_playing = True FFMPEG_OPTIONS = {"before_options": "-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5", "options":"-vn"} YDL_OPTIONS = {"format":"bestaudio"} # 取出队列第一首歌 url = self.queue.pop(0) with youtube_dl.YoutubeDL(YDL_OPTIONS) as ydl: info = ydl.extract_info(url, download=False) url2 = info["formats"][0]["url"] # 异步方法要加await,和play命令里的调用逻辑保持一致 self.vc.play(await discord.FFmpegOpusAudio.from_probe(url2, **FFMPEG_OPTIONS), after=lambda e: self.siguiente()) else: self.is_playing = False
- 修改play命令的判断逻辑,补全
is_playing的括号,删掉多余的siguiente调用:
# 原判断改为 elif len(self.queue) > 0 and ctx.voice_client.is_playing(): # ...原有搜索添加队列逻辑不变 await ctx.send(f"Se ha añadido https://www.youtube.com/watch?v={url}, a la cola ") # 删掉这行 await self.siguiente(),歌曲播放结束会自动触发下一首
- 所有用到全局
queue的地方都替换为self.queue,删掉limpiar_cola方法里的global queue声明。
内容的提问来源于stack exchange,提问作者iMaGiikz
相关产品推荐
相关产品推荐

