You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Discord.py音乐机器人报错:缺少必填位置参数'ctx'

Discord音乐机器人Skip命令执行报错问题

问题概述

开发Discord音乐机器人时,所有命令均触发相同异常,以Skip命令为例,执行时提示缺少ctx参数。怀疑是否因使用discord.py已弃用语法导致,寻求解决方案。

相关代码片段

音乐Cog实现(dustobot.py)

class music(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

        self.is_playing = False
        self.is_paused = False

        self.music_queue = []
        self.YDL_OPTIONS = {"format": "bestaudio", "noplaylist": "True"}
        self.FFMPEG_OPTIONS = {"before_options": "-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5", "options": "-vn"}

        self.vc = None

        
    async def play_music(self, ctx):
        if len(self.music_queue) > 0:
            self.is_playing = True
            m_url = self.music_queue[0][0]["source"]

            if self.vc == None or not self.vc.is_connected():
                self.vc == await self.music_queue[0][1].connect()

                if self.vc == None:
                    await ctx.send("抱歉,我无法加入语音频道")
                    return
            else:
                await self.vc.move_to(self.music_queue[0][1])
            
            self.music_queue.pop(0)

            self.vc.play(discord.FFmpegPCMAudio(m_url, **self.FFMPEG_OPTIONS), after=lambda e: self.play_next())

        else:
            self.is_playing = False

    
    def play_next(self):
        if len(self.music_queue) > 0:
            self.is_playing = True

            m_url = self.music_queue[0][0]["source"]

            self.music_queue.pop(0)

            self.vc.play(discord.FFmpegPCMAudio(m_url, **self.FFMPEG_OPTIONS), after=lambda e: self.play_next())
        else:
            self.is_playing = False


    def search(self, item):
        with YoutubeDL(self.YDL_OPTIONS) as ydl:
            try:
                info = ydl.extract_info("ytsearch:{0}".format(item), download=False)["entries"][0]
            except Exception:
                return False
        return {"source": info["formats"][0]["url"], "title": info["title"]}

async def setup(client):
    await client.add_cog(music(client))

Bot类与Skip命令(bot.py)

class MyBot(commands.Bot):
    async def setup_hook(self):
        await self.load_extension("dustobot")

@commands.command(aliases=["s"], help="跳过当前播放的歌曲")
    async def skip(self, ctx, *args):
        if self.vc != None and self.vc:
            self.vc.stop()
            await self.play_music(ctx) # 播放队列中的下一首歌曲

主入口文件(main.py)

import os
import discord
from dustobot import music # 导入音乐类
from dotenv import load_dotenv
from discord.ext import commands

load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')

intents = discord.Intents.default()
intents.message_content = True

client = commands.Bot(command_prefix="!", intents=intents)

client.remove_command("help") # 自定义了help命令


if __name__ == "__main__":
    client.run(TOKEN)

错误信息

2023-01-21 12:28:37 ERROR    discord.ext.commands.bot Ignoring exception in command skip
Traceback (most recent call last):
  File "C:\Users\private_path\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\discord\ext\commands\core.py", line 229, in wrapped
    ret = await coro(*args, **kwargs)
TypeError: music.skip() missing 1 required positional argument: 'ctx'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "C:\Users\private_path\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\discord\ext\commands\bot.py", line 1349, in invoke 
    await ctx.command.invoke(ctx)
  File "C:\Users\private_path\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\discord\ext\commands\core.py", line 1023, in invoke
    await injected(*ctx.args, **ctx.kwargs)  # type: ignore
  File "C:\Users\private_path\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\discord\ext\commands\core.py", line 238, in wrapped       
    raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: TypeError: music.skip() missing 1 required positional argument: 'ctx'

疑问

是否因使用discord.py已弃用语法导致该错误?


解决方案

核心问题是命令定义位置错误+语法疏漏,和弃用语法无关:

  1. 命令未绑定到Cog实例:你把skip命令定义在了MyBot类外部,而非music Cog内部,导致命令无法获取Cog实例的上下文,触发缺少ctx的报错。
  2. 赋值运算符错误:play_music方法中self.vc == await ...是比较操作,应改为self.vc = await ...,否则self.vc始终为None,无法正常连接语音频道。

修正步骤:

1. 将Skip命令移入music Cog内部

class music(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        # 其余初始化代码不变

    # 其余方法(play_music、play_next、search)不变

    @commands.command(aliases=["s"], help="跳过当前播放的歌曲")
    async def skip(self, ctx, *args):
        if self.vc is not None and self.vc.is_playing():
            self.vc.stop()
            await self.play_music(ctx)

2. 修正play_music中的赋值错误

将:

self.vc == await self.music_queue[0][1].connect()

改为:

self.vc = await self.music_queue[0][1].connect()

3. 调整main.py使用自定义MyBot类

否则setup_hook不会执行,无法加载Cog:

# main.py
import os
import discord
from bot import MyBot
from dotenv import load_dotenv

load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')

intents = discord.Intents.default()
intents.message_content = True

client = MyBot(command_prefix="!", intents=intents)

client.remove_command("help")

if __name__ == "__main__":
    client.run(TOKEN)

调整后命令可正确绑定到Cog实例,获取ctx参数,同时解决语音连接的赋值问题。


内容的提问来源于stack exchange,提问作者Coder_0511

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 23:20:29