raise KeyboardInterrupt() KeyboardInterrupt | asyncio.exceptions.CancelledError

Question:

An error occurs when disabling the bot with Ctrl+C in VSCode
Error:

Traceback (most recent call last):
  File "C:Program FilesPython311Libasynciorunners.py", line 118, in run
    return self._loop.run_until_complete(task)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:Program FilesPython311Libasynciobase_events.py", line 653, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "E:BotsDiscordtbotmain.py", line 46, in main
    await bot.start(config['token'])
  File "C:UsersArtemAppDataRoamingPythonPython311site-packagesdiscordclient.py", line 746, in start
    await self.connect(reconnect=reconnect)
  File "C:UsersArtemAppDataRoamingPythonPython311site-packagesdiscordclient.py", line 627, in connect
    await self.ws.poll_event()
  File "C:UsersArtemAppDataRoamingPythonPython311site-packagesdiscordgateway.py", line 619, in poll_event
    msg = await self.socket.receive(timeout=self._max_heartbeat_timeout)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:UsersArtemAppDataRoamingPythonPython311site-packagesaiohttpclient_ws.py", line 229, in receive
    msg = await self._reader.read()
          ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:UsersArtemAppDataRoamingPythonPython311site-packagesaiohttpstreams.py", line 657, in read
    return await super().read()
           ^^^^^^^^^^^^^^^^^^^^
  File "C:UsersArtemAppDataRoamingPythonPython311site-packagesaiohttpstreams.py", line 616, in read
    await self._waiter
asyncio.exceptions.CancelledError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "E:BotsDiscordtbotmain.py", line 49, in <module>
    asyncio.run(main())
  File "C:Program FilesPython311Libasynciorunners.py", line 190, in run
    return runner.run(main)
           ^^^^^^^^^^^^^^^^
  File "C:Program FilesPython311Libasynciorunners.py", line 123, in run
    raise KeyboardInterrupt()
KeyboardInterrupt

main.py:

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

file = open('config.json', 'r')
config = json.load(file)

intents = discord.Intents.all()
intents.message_content = True
bot = commands.Bot((config['prefix']), intents=intents, help_command=None)


@bot.event
async def on_ready():
    await bot.tree.sync()
    await bot.change_presence(status=discord.Status.dnd, activity=discord.Game(name=".help"))
    print('Bot connected')

@bot.event
async def on_command_error(ctx, error):
    if isinstance(error, commands.CommandNotFound):
        embed = discord.Embed(
        description = f'{ctx.author.mention}, сommand not found!', 
        colour = discord.Color.red()
        )
        sent_message = await ctx.send(embed=embed)
        await asyncio.sleep(20)
        await sent_message.delete() 

async def load():
    for filename in os.listdir('./cogs'):
        if filename.endswith('.py'):
            await bot.load_extension(f'cogs.{filename[:-3]}')

async def main():
    await load()
    await bot.start(config['token'])


asyncio.run(main())

The bot uses hybrid commands, if you try to replace asyncio.run with bot.run, the slash commands do not work. Is this a bug or is it considered normal? If it is an error, can you help me solve it? Thanks.
P.S. Python v3.11.1, discord.py v2.2.2

Asked By: Effectys

||

Answers:

When you use Ctrl+C the os sends a signal to your code, if you want, you can handle it by a try-except. By the way, you can ignore it. check this thread.

Answered By: Mr.Ziri

The error is expected – you can either handle it yourself or use bot.run to run the bot instead. bot.run will work as they’re catching the error. To emulate it:

try:
    asyncio.run(main())
except KeyboardInterrupt:
    print("Exiting...")

Though, the better approach is to use the builtin bot.run command. To use that and register your commands; we need to move the loading of them into the setup_hook method. We can either subclass commands.Bot and override it, or set the function.

To do the latter:

async def my_setup_func()
    for filename in os.listdir('./cogs'):
        if filename.endswith('.py'):
            await bot.load_extension(f'cogs.{filename[:-3]}')


bot.setup_hook = my_setup_func
bot.run(config["token"])

To do the former:

class MyBot(commands.Bot):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    async def setup_hook(self) -> None:
        for filename in os.listdir('./cogs'):
            if filename.endswith('.py'):
                await bot.load_extension(f'cogs.{filename[:-3]}')

intents = discord.Intents.all()
intents.message_content = True
bot = MyBot((config['prefix']), intents=intents, help_command=None)

# rest of your setup code

bot.run(config["token"])

Hope that makes some sense. Some of the examples make use of the latter technique.

Answered By: ESloman