【问题标题】:catching extension exceptions捕获扩展异常
【发布时间】:2021-09-06 23:05:18
【问题描述】:

所以我想捕获加载扩展时会引发的每个异常,我在文档中找到了这些

扩展错误:

  • 扩展已加载
  • ExtensionNotLoaded
  • NoEntryPointError
  • 扩展失败
  • ExtensionNotFound

这是我一直在尝试使用的代码,但我太笨了

@bot.command()
async def reload(ctx, extension):

    try:
        bot.reload_extension(f'Cogs.{extension}')
        await ctx.send(f'reloaded {extension}')

        # raise commands.ExtensionNotFound(extension) # makes **ExtensionNotFound* prints

    except commands.ExtensionNotLoaded: # this works
        bot.load_extension(f'Cogs.{extension}')
        await ctx.send(f'{extension} was not loaded in the first place but i loaded it up for you')

    except commands.ExtensionNotFound: # doesn't catch actual exception unless it's raised
        await ctx.send('commands.ExtensionNotFound')

    except commands.ExtensionError: # didn't test coz i got hung up on the last exception
        await ctx.send('commands.ExtensionError')

    except commands.ExtensionFailed: # didn't test
        await ctx.send('commands.ExtensionFailed')

    except commands.ExtensionAlreadyLoaded: # didn't test
        await ctx.send('commands.ExtensionAlreadyLoaded')

所以我想要的是一个捕获扩展异常的工作示例(与我的弱代码不同,它确实有效)

编辑1: 如果我使用不存在的 cog !reload not_a_real_cog 调用 reload 函数,我会收到以下异常:

Ignoring exception in command reload:
Traceback (most recent call last):
  File "d:\Discord bots\Discord bot - Cogs V1\main.py", line 136, in reload
    bot.reload_extension(f'Cogs.{extension}')
  File "C:\Users\Bruh\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\bot.py", line 759, in reload_extension  
    raise errors.ExtensionNotLoaded(name)
discord.ext.commands.errors.ExtensionNotLoaded: Extension 'Cogs.not_a_real_cog' has not been loaded.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\Bruh\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 85, in wrapped
    ret = await coro(*args, **kwargs)
  File "d:\Discord bots\Discord bot - Cogs V1\main.py", line 142, in reload
    bot.load_extension(f'Cogs.{extension}')
  File "C:\Users\Bruh\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\bot.py", line 676, in load_extension    
    raise errors.ExtensionNotFound(name)
discord.ext.commands.errors.ExtensionNotFound: Extension 'Cogs.not_a_real_cog' could not be loaded.

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

Traceback (most recent call last):
  File "C:\Users\Bruh\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\bot.py", line 939, in invoke
    await ctx.command.invoke(ctx)
  File "C:\Users\Bruh\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 863, in invoke
    await injected(*ctx.args, **ctx.kwargs)
  File "C:\Users\Bruh\AppData\Local\Programs\Python\Python39\lib\site-packages\discord\ext\commands\core.py", line 94, in wrapped
    raise CommandInvokeError(exc) from exc
discord.ext.commands.errors.CommandInvokeError: Command raised an exception: ExtensionNotFound: Extension 'Cogs.not_a_real_cog' could not be loaded.

通过@CrazyChucky 在 cmets 中提供的方法再次测试ExtensionNotFound .. 我想我误解了实际捕捉它的异常是什么,尽管我试图捕捉它:

  • ExtensionNotLoaded
  • ExtensionNotFound
  • CommandInvokeError

但我什么也没抓到

【问题讨论】:

  • 所以当你手动提出ExtensionNotFound时,你的except子句就被输入了。您以什么其他方式测试了该错误(我想是删除/重命名扩展文件)?会发生什么?
  • 我想我可能误解了我实际上试图捕获它的异常,因为我尝试了你的方法并且它当前捕获了异常,我似乎无法捕获的异常是什么时候我尝试重新加载一个不存在的齿轮。
  • 你明白了,好吧。更仔细地查看您的错误消息。 bot.reload_extension(...) 行抛出 ExtensionNotLoaded,这会导致代码输入您的第一个 except 子句。然后bot.load_extension(...), inside 该子句抛出ExtensionNotFound,因为它找不到要加载的扩展。没有内部的 except 来捕捉它,所以异常会传播。
  • 哦!我明白了我的错误,我认为只要整个内容都在 try 块中,它就会捕获所有内容,感谢您的帮助!
  • @omar 是的,tryin 中的所有内容都将被捕获,但 excepttry 处于同一级别,在其下方,所以不在里面。这意味着 except 中的所有内容都将不会被捕获,因为它不在 try 中。

标签: python discord discord.py


【解决方案1】:

根据您的 cmets,我发现您不清楚 try/except clauses 的工作原理;您只能在try 部分捕获异常,而try 只会捕获它遇到的第一个异常,立即中止并转到相应的except(或else)子句。

在这种情况下,您需要将一个 try/except 嵌套在另一个中,请记住,无论您是 loading 还是 reloading,您都可能生成多个相同的错误,并且您不希望您的代码重复。

@bot.command()
async def reload(ctx, extension):
    try:

        # This inner try/except only cares about whether the extension
        # can be REloaded, or whether it needs to be loaded from
        # scratch.
        try:
            await ctx.send(f'Attempting to reload {extension} extension...')
            bot.reload_extension(f'cogs.{extension}')
        except commands.ExtensionNotLoaded:
            await ctx.send(f'{extension} is not currently loaded. Attempting '
                            'to load...')
            bot.load_extension(f'cogs.{extension}')

        await ctx.send(f'{extension} has been freshly loaded.')

    # These except clauses will be reached if their exception occurs,
    # regardless of whether or not the inner except clause was entered.

    except commands.ExtensionNotFound:
        await ctx.send(f"Error: {extension} couldn't be found to load."))

    except commands.ExtensionFailed:
        await ctx.send(f'Error: {extension} failed to load properly.')

    except commands.ExtensionError:
        await ctx.send(f'Error: unknown error with {extension}')

注意:Python 中的模块名通常都是小写,所以我将Cogs 重命名为cogs

您可能会被 bot 的 extensions attribute 的存在所诱惑,按照以下方式进行操作:

if extension in bot.extensions:
    bot.reload_extension(f'cogs.{extension}')
else:
    bot.load_extension(f'cogs.{extension}')

但这在像这样的异步环境中是危险的,因为它是一种竞争条件:在您执行in 检查和实际尝试加载/重新加载扩展程序之间,可能有其他用户或进程可能已经加载/卸载了扩展。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-12
    • 1970-01-01
    • 2015-11-10
    • 2013-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-25
    相关资源
    最近更新 更多