discord.py加载扩展报错:'Client'对象无'load_extension'属性
问题描述
尝试将discord.py的命令拆分到music.py文件中时,运行出现错误:AttributeError: 'Client' object has no attribute 'load_extension',此前还遇到过'Client' object has no attribute 'add_cog'错误。
以下是原代码:
main.py
import discord import music from discord.ext import commands client = commands.Bot(command_prefix="!", intents=discord.Intents.all()) token = "" cogs = [music] @client.event async def on_ready(): await client.load_extension(cogs.commands) print(f"Logged in as {client.user})") client.run(token)
music.py
import discord from discord.ext import commands import youtube_dl class music(commands.Cog): def __init__(self, client): self.client = client @commands.command() async def join(self, ctx): if ctx.author.voice is None: await ctx.send("First join to voice channel") voicechannel = ctx.author.voice.channel if ctx.voicechannel is None: await voicechannel.join() else: await voicechannel.move_to(ctx.voicechannel) @commands.command() async def disconnect(self, ctx): await ctx.voice_client.disconnect() @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 = ydl.extract_info(url, download=False) url2 = info['formats'][0]['url'] source = await discord.FFmpegOpusAudio.from_probe(url2, **FFMPEG_OPTIONS) vc.play(source) @commands.command() async def resume(self, ctx): await ctx.voice_client.resume() await ctx.send("resumed") @commands.command() async def pause(self, ctx): await ctx.voice_client.pause() await ctx.send("paused") async def setup(client): await client.add_cog(music(client))
错误原因及修复方案
1. 扩展加载方式错误
你创建的是commands.Bot实例(继承自Client),但加载扩展的代码写法错误:
await client.load_extension(cogs.commands)是错误用法,load_extension需要传入模块名字符串(比如"music"),而非模块对象的属性cogs = [music]是导入的模块对象列表,正确加载方式是遍历列表,传入模块的名称
2. join命令逻辑错误
- 当
ctx.author.voice is None时,尝试获取ctx.author.voice.channel会直接报错,因为ctx.author.voice已经是None - 缩进错误:频道判断和连接代码应放在
if块外部,仅当用户在语音频道时执行
3. 额外注意:youtube_dl已停止维护
youtube_dl目前不再更新,建议替换为yt-dlp,安装命令:pip install yt-dlp,代码中只需将import youtube_dl改为import yt_dlp as youtube_dl即可。
修正后的代码
main.py
import discord import music from discord.ext import commands client = commands.Bot(command_prefix="!", intents=discord.Intents.all()) token = "" cogs = [music] @client.event async def on_ready(): # 遍历加载所有cog模块 for cog in cogs: await client.load_extension(cog.__name__) print(f"Logged in as {client.user}") # 修正字符串闭合错误 client.run(token)
music.py
import discord from discord.ext import commands # 推荐替换为yt-dlp # import yt_dlp as youtube_dl import youtube_dl class Music(commands.Cog): # 类名首字母大写符合PEP8规范 def __init__(self, client): self.client = client @commands.command() async def join(self, ctx): if ctx.author.voice is None: return await ctx.send("请先加入一个语音频道!") voice_channel = ctx.author.voice.channel if ctx.voice_client is None: await voice_channel.join() else: await ctx.voice_client.move_to(voice_channel) # 修正move_to调用对象 @commands.command() async def disconnect(self, ctx): if ctx.voice_client: await ctx.voice_client.disconnect() else: await ctx.send("我不在任何语音频道中!") @commands.command() async def play(self, ctx, url): if not ctx.voice_client: return await ctx.send("请先让我加入语音频道!") ctx.voice_client.stop() FFMPEG_OPTIONS = { 'before_options': '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5', 'options': '-vn' } YDL_OPTIONS = {'format': "bestaudio"} with youtube_dl.YoutubeDL(YDL_OPTIONS) as ydl: info = ydl.extract_info(url, download=False) url2 = info['formats'][0]['url'] source = await discord.FFmpegOpusAudio.from_probe(url2, **FFMPEG_OPTIONS) ctx.voice_client.play(source) await ctx.send(f"正在播放: {info['title']}") @commands.command() async def resume(self, ctx): if ctx.voice_client and ctx.voice_client.is_paused(): ctx.voice_client.resume() await ctx.send("已恢复播放!") else: await ctx.send("当前没有暂停的音频!") @commands.command() async def pause(self, ctx): if ctx.voice_client and ctx.voice_client.is_playing(): ctx.voice_client.pause() await ctx.send("已暂停播放!") else: await ctx.send("当前没有正在播放的音频!") async def setup(client): await client.add_cog(Music(client))
内容的提问来源于stack exchange,提问作者Kubzel
相关产品推荐
相关产品推荐

