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

如何让Python Discord Bot在提及非服务器成员时发送嵌入错误消息

Discord Bot赞美命令:处理不存在的服务器成员问题

问题描述

开发Python Discord Bot时,实现了!compliment命令用于给提及成员或调用者发送随机赞美。但当输入!compliment <不在服务器的用户名>时,终端会抛出MemberNotFound错误,而非在服务器内发送嵌入错误消息。需求是:先检查提及用户是否在当前服务器,若不在则向命令调用者发送红色嵌入错误提示。

现有代码

# (4) Compliment command.
@commands.command(
    name = 'compliment',
    aliases = ['Compliment', 'COMPLIMENT'],
    description = 'Gives a random compliment.'
)
async def compliment(self, ctx, *, member: discord.Member = None):
    try:
        await ctx.typing()

        response = random.choice(Compliments)

        if member is not None:
            if member.guild != ctx.guild:
                embed = discord.Embed(
                    title = '__Error__',
                    description = 'This member is not on this server.',
                    color = discord.Color.red()
                )
                await ctx.reply(embed = embed)
            
            else:
                embed = discord.Embed(
                    title = '__Compliment__',
                    description = f'{member.mention}, {response}',
                    color = discord.Color.dark_blue()
                )
                await ctx.reply(embed = embed)

        if member is None:
            embed = discord.Embed(
                title = '__Compliment__',
                description = f'{ctx.author.mention}, {response}',
                color = discord.Color.dark_blue()
            )
            await ctx.reply(embed = embed)

    except Exception as e:
        print(f'An error occurred in compliment command: {e}')

报错信息

Traceback (most recent call last):
  File "C:\Users\xesch\AppData\Local\Programs\Python\Python312\Lib\site-packages\discord\ext\commands\bot.py", line 1350, in invoke
    await ctx.command.invoke(ctx)
  File "C:\Users\xesch\AppData\Local\Programs\Python\Python312\Lib\site-packages\discord\ext\commands\core.py", line 1021, in invoke
    await self.prepare(ctx)
  File "C:\Users\xesch\AppData\Local\Programs\Python\Python312\Lib\site-packages\discord\ext\commands\core.py", line 938, in prepare
    await self._parse_arguments(ctx)
  File "C:\Users\xesch\AppData\Local\Programs\Python\Python312\Lib\site-packages\discord\ext\commands\core.py", line 853, in _parse_arguments
    kwargs[name] = await self.transform(ctx, param, attachments)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\xesch\AppData\Local\Programs\Python\Python312\Lib\site-packages\discord\ext\commands\core.py", line 715, in transform
    return await run_converters(ctx, converter, argument, param)  # type: ignore
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\xesch\AppData\Local\Programs\Python\Python312\Lib\site-packages\discord\ext\commands\converter.py", line 1355, in run_converters
    return await _actual_conversion(ctx, converter, argument, param)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\xesch\AppData\Local\Programs\Python\Python312\Lib\site-packages\discord\ext\commands\converter.py", line 1237, in _actual_conversion
    return await converter().convert(ctx, argument)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\xesch\AppData\Local\Programs\Python\Python312\Lib\site-packages\discord\ext\commands\converter.py", line 276, in convert
    raise MemberNotFound(argument)
discord.ext.commands.errors.MemberNotFound: Member "@lakshey" not found.

问题原因

discord.Member转换器会在命令执行前尝试将输入的参数转换为服务器成员对象,如果找不到匹配成员,会直接抛出MemberNotFound异常,这个过程发生在代码中的try块之前,所以try-except无法捕获该错误。

解决方案

方法一:使用命令错误处理装饰器(推荐)

利用discord.py提供的命令错误处理机制,专门捕获MemberNotFound异常并发送嵌入错误消息,同时修复原代码中重复执行的逻辑问题:

# (4) Compliment command.
@commands.command(
    name='compliment',
    aliases=['Compliment', 'COMPLIMENT'],
    description='Gives a random compliment.'
)
async def compliment(self, ctx, *, member: discord.Member = None):
    await ctx.typing()
    response = random.choice(Compliments)

    if member is not None:
        # 经过转换器验证后,member必然属于当前服务器,此判断可省略
        if member.guild != ctx.guild:
            embed = discord.Embed(
                title='__Error__',
                description='This member is not on this server.',
                color=discord.Color.red()
            )
            await ctx.reply(embed=embed)
        else:
            embed = discord.Embed(
                title='__Compliment__',
                description=f'{member.mention}, {response}',
                color=discord.Color.dark_blue()
            )
            await ctx.reply(embed=embed)
    elif member is None:
        embed = discord.Embed(
            title='__Compliment__',
            description=f'{ctx.author.mention}, {response}',
            color=discord.Color.dark_blue()
        )
        await ctx.reply(embed=embed)

# 命令专属错误处理函数
@compliment.error
async def compliment_error(ctx, error):
    if isinstance(error, commands.MemberNotFound):
        embed = discord.Embed(
            title='__Error__',
            description='This member is not on this server.',
            color=discord.Color.red()
        )
        await ctx.reply(embed=embed)
    else:
        print(f'An error occurred in compliment command: {error}')

方法二:手动处理成员查找

如果需要更灵活的成员匹配逻辑,可以接收字符串参数,自行在服务器内查找成员:

# (4) Compliment command.
@commands.command(
    name='compliment',
    aliases=['Compliment', 'COMPLIMENT'],
    description='Gives a random compliment.'
)
async def compliment(self, ctx, *, member_str: str = None):
    await ctx.typing()
    response = random.choice(Compliments)

    if member_str is not None:
        member = None
        # 处理用户提及格式(如<@123456>)
        if member_str.startswith('<@') and member_str.endswith('>'):
            user_id = member_str.strip('<@!>')
            try:
                member = ctx.guild.get_member(int(user_id))
            except ValueError:
                pass
        # 按用户名查找
        if not member:
            member = discord.utils.get(ctx.guild.members, name=member_str)
        # 按昵称查找
        if not member:
            member = discord.utils.get(ctx.guild.members, display_name=member_str)
        
        if not member:
            # 未找到成员,发送错误消息
            embed = discord.Embed(
                title='__Error__',
                description='This member is not on this server.',
                color=discord.Color.red()
            )
            await ctx.reply(embed=embed)
            return
        
        # 找到成员,发送赞美
        embed = discord.Embed(
            title='__Compliment__',
            description=f'{member.mention}, {response}',
            color=discord.Color.dark_blue()
        )
        await ctx.reply(embed=embed)
    else:
        # 未提及成员,给调用者发赞美
        embed = discord.Embed(
            title='__Compliment__',
            description=f'{ctx.author.mention}, {response}',
            color=discord.Color.dark_blue()
        )
        await ctx.reply(embed=embed)

说明

  • 方法一遵循discord.py的设计规范,代码简洁易维护,是优先推荐的方案。
  • 方法二适合需要自定义成员匹配逻辑的场景,但需要自行处理各种成员标识格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 18:17:33