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
相关产品推荐
相关产品推荐

