Reputation: 77
So I want to catch every exception that would be raised from loading extensions, of which i found these in the docs
ExtensionErrors:
This is the code I've been trying to get something working with, but i is too dumb
@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')
So what I want is a working example of catching the extension exceptions (that.. unlike my weak arse code, does actually work)
Edit1:
If I call the reload function with a none existing cog !reload not_a_real_cog
I get the following exception:
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.
Testing ExtensionNotFound
again by the methods provided by @CrazyChucky in the comments.. I think i misunderstood what the exception IS to actually to catch it, though I tried to catch:
ExtensionNotLoaded
ExtensionNotFound
CommandInvokeError
But i catched nothing
Upvotes: 0
Views: 396
Reputation: 3518
Based on your comments, I see that you were unclear on how try
/except
clauses work; you can only catch an exception in the try
part, and a try
will only catch the first exception it encounters, immediately aborting and going to the corresponding except
(or else
) clause.
In this case, you'll want to nest one try
/except
inside another, keeping in mind that you can generate several of the same errors whether you're loading
or reloading
, and you don't want your code to repeat itself.
@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}')
Note: module names in Python are usually all lowercase by convention, so I renamed Cogs
to cogs
.
You might be tempted by the existence of the bot's extensions
attribute to do something along these lines:
if extension in bot.extensions:
bot.reload_extension(f'cogs.{extension}')
else:
bot.load_extension(f'cogs.{extension}')
But this is dangerous in an asynchronous environment like this, because it's a race condition: it's possible that between the time you perform the in
check and when you actually try to load/reload the extension, some other user or process could potentially have loaded/unloaded the extension.
Upvotes: 1