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

如何在discord.py的Cogs中全局处理app_command错误?

问题描述

我开发的Discord机器人主要使用Cogs和app_commands,需要一个满足以下两个要求的错误处理器:

  1. 在聊天中发送消息或响应interaction返回错误提示
  2. 不在控制台输出大量错误信息,仅输出简单的「某用户尝试使用某命令」或不输出

目前我实现了单命令的错误处理:

@app_commands.command(name="test", description="are u mod")
@app_commands.checks.has_permissions(moderate_members=True)
async def test(self, interaction: discord.Interaction):
    await interaction.response.send_message("you are a mod!")

@test.error
async def test_error(self, interaction: discord.Interaction, error):
    print(f"{interaction.user} tried to use the `test` command")
    await interaction.response.send_message("no")

但问题是每个管理员命令都要创建对应的错误处理函数,我需要一个全局错误处理器,在任何「缺少管理员权限」检查失败时执行上述逻辑。

我尝试过以下全局错误处理代码:

@bot.tree.error
async def on_app_command_error(interaction: discord.Interaction, error: app_commands.AppCommandError):
    if isinstance(error, app_commands.CommandOnCooldown):
        return await interaction.response.send_message(error, ephemeral = True)
    elif isinstance(error, app_commands.BotMissingPermissions):
        return await interaction.response.send_message(error, ephemeral = True)
    else:
        await interaction.response.send_message("An error occurred!", ephemeral = True)
        raise error

但它仅能返回通用错误提示,无法匹配具体错误类型,且仍会在控制台输出大量错误信息,不满足我的需求。

我的机器人基本结构如下:
main.py

bot = commands.Bot(command_prefix='!', intents=discord.Intents.all())

@bot.event
async def on_ready():
    print(f'{bot.user} has connected to Discord!')
    try:
        synced = await bot.tree.sync()
        print(f"Synced {len(synced)} command(s)")
    except Exception as e:
        print(e)


async def load_cogs():
    for file in os.listdir('./cogs'):
        if file.endswith('.py'):
            await bot.load_extension(f'cogs.{file[:-3]}')


asyncio.run(load_cogs())
bot.run(os.getenv('bot_key'))

examplecog.py

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

    @commands.Cog.listener()
    async def on_ready(self):
        print(self.__class__.__name__ + " cog loaded")

    @app_commands.command(name="test", description="are u mod")
    @app_commands.checks.has_permissions(moderate_members=True)
    async def test(self, interaction: discord.Interaction):
        await interaction.response.send_message("you are a mod!")


async def example(bot):
    await bot.add_cog(errors(bot))
解决方案

要实现满足需求的全局错误处理器,需精准匹配权限错误类型,同时避免抛出错误导致控制台输出冗余信息,具体实现如下:

1. 精准匹配错误类型

当@app_commands.checks.has_permissions检查失败时,抛出的是app_commands.MissingPermissions错误(用户缺少权限),而非通用错误。需区分该类型与BotMissingPermissions(机器人缺少权限)。

2. 编写全局错误处理函数

修改@bot.tree.error装饰的全局处理函数,针对性处理各类错误,且不抛出错误:

@bot.tree.error
async def on_app_command_error(interaction: discord.Interaction, error: app_commands.AppCommandError):
    # 用户缺少权限的处理逻辑
    if isinstance(error, app_commands.MissingPermissions):
        print(f"{interaction.user} tried to use `{interaction.command.name}` (missing required permissions)")
        await interaction.response.send_message("你没有使用该命令的权限!", ephemeral=True)
        return
    
    # 机器人缺少权限的处理逻辑
    elif isinstance(error, app_commands.BotMissingPermissions):
        await interaction.response.send_message("我没有执行该操作的权限,请检查我的角色设置!", ephemeral=True)
        return
    
    # 命令冷却的处理逻辑
    elif isinstance(error, app_commands.CommandOnCooldown):
        await interaction.response.send_message(f"命令冷却中,请等待{error.retry_after:.1f}秒后再试", ephemeral=True)
        return
    
    # 其他未定义错误的处理
    print(f"Unknown error from {interaction.user} using `{interaction.command.name}`: {type(error).__name__}")
    await interaction.response.send_message("发生了未知错误!", ephemeral=True)

3. 封装到Cog(推荐)

若想将错误逻辑独立封装,创建cogs/errors.py文件:

import discord
from discord import app_commands
from discord.ext import commands

class Errors(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        self.bot.tree.error(coro=self.on_app_command_error)

    async def on_app_command_error(self, interaction: discord.Interaction, error: app_commands.AppCommandError):
        if isinstance(error, app_commands.MissingPermissions):
            print(f"{interaction.user} tried to use `{interaction.command.name}` (missing permissions)")
            await interaction.response.send_message("你没有权限使用这个命令!", ephemeral=True)
            return
        
        elif isinstance(error, app_commands.BotMissingPermissions):
            await interaction.response.send_message("我缺少执行该操作的权限,请检查我的角色权限!", ephemeral=True)
            return
        
        elif isinstance(error, app_commands.CommandOnCooldown):
            await interaction.response.send_message(f"命令正在冷却,{error.retry_after:.1f}秒后再试", ephemeral=True)
            return
        
        print(f"Error from {interaction.user} using `{interaction.command.name}`: {type(error).__name__}")
        await interaction.response.send_message("出现了未知错误", ephemeral=True)

async def setup(bot):
    await bot.add_cog(Errors(bot))

只要该文件放在./cogs目录下,main.py的load_cogs函数会自动加载。

关键注意事项

  • 不要在处理函数中使用raise error,否则会触发Discord.py输出完整错误堆栈,违背“不输出大量错误信息”的需求。
  • 使用ephemeral=True可让错误提示仅对触发用户可见,避免频道刷屏。
  • 通过interaction.command.name自动获取命令名称,无需硬编码,适配所有命令。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 07:03:17