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

Discord.py中asyncio.timeout错误无法被on_command_error捕获的问题

Discord.py中wait_for超时错误无法被on_command_error捕获的问题

问题重现

我是Discord Python开发新手,在用wait_for()时遇到错误处理问题:它抛出的asyncio.TimeoutError无法被on_command_error事件捕获。以下是我的代码:

import discord
import asyncio
from discord.ext import commands

intents = discord.Intents.all()
bot = commands.Bot(command_prefix="--", intents=intents)

@bot.event
async def on_command_error(ctx:commands.Context, error):
    print(f"{error} in command: {ctx.invoked_with}")
    if isinstance(error, asyncio.exceptions.TimeoutError):
        print('aaaa')
    if isinstance(error, asyncio.TimeoutError):
        print('bbbb')
    else:
       raise error

@bot.command()
async def test(ctx):
    def check(m):
        return m.channel == ctx.channel
    await bot.wait_for('message', timeout=3, check=check)

bot.run("token")

运行后报错:

File "C:\Users\xstri\\AppData\Local\Programs\Python\Python38\lib\site-packages\discord\ext\commands\core.py", line 229, in wrapped
    ret = await coro(*args, **kwargs)
  File "d:/Python/Python Project/main.py", line 22, in test
    await bot.wait_for('message', timeout=3, check=check)
  File "C:\Users\xstri\AppData\Local\Programs\Python\Python38\lib\asyncio\tasks.py", line 501, in wait_for
    raise exceptions.TimeoutError()
asyncio.exceptions.TimeoutError

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

Traceback (most recent call last):
  File "C:\Users\xstri\AppData\Local\Programs\Python\Python38\lib\site-packages\discord\client.py", line 409, in _run_event
    await coro(*args, **kwargs)
  File "d:/Python/Python Project/main.py", line 16, in on_command_error
    raise error
  File "C:\Users\xstri\AppData\Local\Programs\Python\Python38\lib\site-packages\discord\ext\commands\bot.py", line 1349, in invoke
    await ctx.command.invoke(ctx)
  File "C:\Users\xstri\AppData\Local\Programs\Python\Python38\lib\site-packages\discord\ext\commands\core.py", line 1023, in invoke
    await injected(*ctx.args, **ctx.kwargs)  # type: ignore
  File "C:\Users\xstri\AppData\Local\Programs\Python\Python38\lib\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: TimeoutError:

问题原因

discord.py的命令执行框架会把命令内部抛出的所有异常包装成CommandInvokeError,再传递给on_command_error事件。你直接判断error是否为asyncio.TimeoutError不成立,因为此时error的实际类型是CommandInvokeError,原始的TimeoutError被存储在它的original属性中。

解决方法

有两种可行的解决方式:

方法一:在on_command_error中解包CommandInvokeError

修改on_command_error事件,先检查是否为CommandInvokeError,再获取原始异常进行判断:

@bot.event
async def on_command_error(ctx:commands.Context, error):
    print(f"{error} in command: {ctx.invoked_with}")
    # 解包原始异常
    original_error = error.original if hasattr(error, 'original') else error
    if isinstance(original_error, asyncio.TimeoutError):
        print('捕获到超时错误了!')
        await ctx.send('等待超时,请重新发起命令')
    else:
       raise error

方法二:在命令内部直接捕获超时错误

如果只需要针对特定命令处理超时,可以直接在test命令里用try-except捕获:

@bot.command()
async def test(ctx):
    def check(m):
        return m.channel == ctx.channel
    try:
        await bot.wait_for('message', timeout=3, check=check)
    except asyncio.TimeoutError:
        print('捕获到超时错误')
        await ctx.send('等待超时!')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 22:25:30