discord.ext.commands 报CommandNotFound:未找到自定义'rank'命令排查
问题根因定位
- 语法错误导致模块完全加载失败
你贴的代码最后一行await ctx.channel.send(embed=embed)"多了一个多余的双引号,会直接触发Python语法错误,整个包含rank命令的模块无法被正常导入,所有写在这个文件里的命令都不会被注册到Bot实例上。 - 命令注册失败核心原因(对应代码第三行函数定义问题)
你定义命令的函数签名是async def rank(self, ctx, rank):,存在两个会直接导致命令不被加载的错误:- 如果这个函数是写在普通Python脚本(非Cog类结构)中,参数列表里多了
self参数:discord.py在注册命令时会严格校验函数参数顺序,要求普通脚本的命令第一个参数必须是ctx,多余的位置参数会导致装饰器直接丢弃这个命令,不会将其加入Bot的命令列表,自然会触发CommandNotFound报错。 - 参数列表里多了一个必填位置参数
rank:这个参数没有设置默认值,意味着用户直接调用!rank不带任何额外参数时,discord.py会判定为参数缺失,甚至在命令注册阶段因为参数逻辑校验不通过,直接拒绝加载这个命令。
- 如果这个函数是写在普通Python脚本(非Cog类结构)中,参数列表里多了
- 装饰器作用域问题(对应代码第二行装饰器问题)
如果你是把这个命令写在Cog类结构中,却没有实现对应的Cog加载逻辑(比如没有写async def setup(bot): await bot.add_cog(你的Cog类(bot))的代码,也没有在Bot初始化时调用add_cog把类加进去),哪怕装饰器正常运行,对应的命令方法也不会被绑定到Bot实例上,依然会触发命令找不到的报错。 - 局部变量命名冲突
函数参数里定义了rank,后面计算排行榜位置的时候又重新赋值了rank = 0做计数变量,哪怕命令最终能正常加载,也会出现变量覆盖的逻辑错误。 - 执行顺序错误
刚进入函数就执行await ctx.send(rank),没有先判断当前频道是不是允许响应的bot_channel,会导致不管在哪个频道调用命令都会先发送无意义的内容。 - 旧API兼容问题
代码里使用的ctx.author.avatar_url是discord.py 1.x版本的写法,在2.x版本中已经替换为ctx.author.avatar.url,不做修改会触发属性不存在的报错。
修正后的可运行代码参考
bot_channel = 替换为你实际的bot专属频道ID leveling = 你的MongoDB集合对象(和原逻辑保持一致即可) @commands.command() async def rank(ctx): # 先校验频道权限 if ctx.channel.id != bot_channel: return # 查询用户等级数据 stats = leveling.find_one({"id": ctx.author.id}) if stats is None: embed = discord.Embed(description="You haven't sent any messages, no rank!!!") await ctx.channel.send(embed=embed) return # 计算等级和进度 xp = stats["xp"] lvl = 0 user_rank = 0 while True: if xp < ((50*(lvl**2))+(50*lvl)): break lvl += 1 xp -= (50 * (lvl - 1) ** 2) + (50 * (lvl - 1)) boxes = int((xp/(200*((1/2) * lvl)))*20) # 计算用户全服排名 rankings = leveling.find().sort("xp", -1) for x in rankings: user_rank += 1 if stats["id"] == x["id"]: break # 构建嵌入消息 embed = discord.Embed(title=f"{ctx.author.name}'s level stats") embed.add_field(name="Name", value=ctx.author.mention, inline=True) embed.add_field(name="XP", value=f"{xp}/{int(200*((1/2)*lvl))}", inline=True) embed.add_field(name="Rank", value=f"{user_rank}/{ctx.guild.member_count}", inline=True) embed.add_field(name="Progress Bar [lvl]", value=boxes * ":blue_square:" + (20-boxes) * ":white_large_square", inline=False) embed.set_thumbnail(url=ctx.author.avatar.url) await ctx.channel.send(embed=embed)
注意:如果你的代码是基于Cog结构开发的,保留函数参数里的self,去掉多余的rank参数即可,同时确保Cog被正常加载到Bot实例。
内容的提问来源于stack exchange,提问作者Ferron12
相关产品推荐
相关产品推荐

