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

使用asyncio运行discord.py机器人时不显示运行时错误

解决discord.py 2.1.0中cog运行时错误不显示的问题

你的问题核心是discord.py默认会捕获命令执行中的未处理异常且未主动输出到终端,和用asyncio.run()启动的方式无关。结合定时任务场景,以下是具体解决方案和最佳实践:

1. 全局命令错误捕获

在自定义Bot类中重写on_command_error方法,统一处理所有命令的异常,确保错误信息输出到终端:

import os
import discord
from discord.ext import commands
import asyncio
import traceback

token = os.environ["BOT_TOKEN"]

class Bot(commands.Bot):
    def __init__(self):
        intents = discord.Intents.default()
        intents.members = True
        intents.message_content = True
        
        description = "bot example."

        super().__init__(
            command_prefix=commands.when_mentioned_or('!'), 
            intents=intents,
            description=description,
            debug=True  # 开发阶段开启,输出更多调试细节
        )

    async def on_ready(self):
        print(f'Logged in as {self.user} (ID: {self.user.id})')
        print('------')

    async def on_command_error(self, ctx, error):
        # 忽略命令不存在的无效请求
        if isinstance(error, commands.CommandNotFound):
            return
        # 打印完整异常栈到终端
        traceback.print_exception(type(error), error, error.__traceback__)
        # 可选:给用户发送错误提示
        await ctx.send("命令执行失败,请稍后重试。")

bot = Bot()

async def load_extensions():
    for f in os.listdir("./cogs"):
        if f.endswith(".py"):
            await bot.load_extension("cogs." + f[:-3])

async def main():
    async with bot:
        await load_extensions()
        await bot.start(token)

asyncio.run(main())

2. 单个命令的针对性异常处理

如果只需要对特定命令做异常处理,直接在命令函数中添加try-except:

from discord.ext import commands
import traceback

class Test(commands.Cog):
    def __init__(self, client):
        self.client = client

    @commands.Cog.listener()
    async def on_ready(self):
        print("Ready")
    
    @commands.command()
    async def command(self, ctx):
        try:
            test_error_message()   # 模拟运行时错误
            print("Command")
        except Exception as e:
            traceback.print_exc()  # 打印错误到终端
            await ctx.send(f"执行出错:{str(e)}")  # 告知用户错误信息

async def setup(client):
    await client.add_cog(Test(client))

3. 定时任务的异常处理

对于tasks.loop装饰的定时任务,有两种处理方式:

方式一:给定时任务单独加异常捕获

from discord.ext import tasks
import traceback

@tasks.loop(seconds=10)
async def avatar_update():
    try:
        # 你的定时任务逻辑
        print("执行头像更新")
        # 模拟错误
        raise ValueError("测试定时任务异常")
    except Exception as e:
        traceback.print_exc()
        # 可选:发送错误通知到指定管理频道
        channel = bot.get_channel(123456789)  # 替换为实际频道ID
        if channel:
            await channel.send(f"定时任务出错:{str(e)}")

方式二:全局异步异常处理器兜底

在main函数中设置事件循环的异常处理器,捕获所有未处理的异步任务异常:

def global_exception_handler(loop, context):
    """全局异步任务异常处理"""
    exception = context.get("exception")
    if exception:
        print("全局异步任务出错:")
        traceback.print_exception(type(exception), exception, exception.__traceback__)
    else:
        print(f"异步任务错误信息:{context['message']}")

async def main():
    loop = asyncio.get_running_loop()
    loop.set_exception_handler(global_exception_handler)
    
    async with bot:
        avatar_update.start()
        await load_extensions()
        await bot.start(token)

最佳实践总结

  • 开发阶段开启Bot的debug=True参数,获取更详细的调试日志
  • 必须配置全局on_command_error,覆盖所有命令的异常捕获
  • 定时任务优先单独加try-except,方便针对性处理;全局异步异常处理器作为兜底
  • 异常信息要同时输出到终端(方便开发调试)和Discord频道(方便管理员知晓)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 01:10:53