Issue
I'm currently creating a discord bot that contains two task loops called check_members
and check_music
.
When a user enters the offline
command, I'd like to gracefully stop these loops. I wrote this piece of code in my Cog class:
class MusicBot(commands.Cog):
# function called when bot is closing.
See [here](https://discordpy.readthedocs.io/en/stable/ext/commands/api.html?highlight=cog_unload#discord.ext.commands.Cog.cog_unload)
def cog_unload(self):
print("Debug")
self.check_members.cancel()
self.check_music.cancel()
print(self.check_members.is_running())
print(self.check_music.is_running())
# example of a task loop I have:
@tasks.loop(seconds=5)
async def check_members(self):
[code...]
In another script, I call the bot.close() function as follows:
await ctx.send("Going offline! See ya later.")
if self.voice is not None:
await self.disconnect()
await self.bot.close()
sys.exit(0)
When a user calls the offline
command, that's what the bot prints out:
Debug
True
Task exception was never retrieved
future: <Task finished name='discord.py: on_message' coro=<Client._run_event() done, defined at /home/liuk23/.local/lib/python3.10/site-packages/discord/client.py:401> exception=SystemExit(0)>
Traceback (most recent call last):
File "/home/liuk23/Desktop/coding/Discord-bot-3/main.py", line 67, in <module>
loop.run_forever()
File "/usr/lib/python3.10/asyncio/base_events.py", line 600, in run_forever
self._run_once()
File "/usr/lib/python3.10/asyncio/base_events.py", line 1896, in _run_once
handle._run()
File "/usr/lib/python3.10/asyncio/events.py", line 80, in _run
self._context.run(self._callback, *self._args)
File "/home/liuk23/.local/lib/python3.10/site-packages/discord/client.py", line 409, in _run_event
await coro(*args, **kwargs)
File "/home/liuk23/.local/lib/python3.10/site-packages/discord/ext/commands/bot.py", line 1392, in on_message
await self.process_commands(message)
File "/home/liuk23/.local/lib/python3.10/site-packages/discord/ext/commands/bot.py", line 1389, in process_commands
await self.invoke(ctx) # type: ignore
File "/home/liuk23/.local/lib/python3.10/site-packages/discord/ext/commands/bot.py", line 1347, in invoke
await ctx.command.invoke(ctx)
File "/home/liuk23/.local/lib/python3.10/site-packages/discord/ext/commands/core.py", line 986, in invoke
await injected(*ctx.args, **ctx.kwargs) # type: ignore
File "/home/liuk23/.local/lib/python3.10/site-packages/discord/ext/commands/core.py", line 190, in wrapped
ret = await coro(*args, **kwargs)
File "/home/liuk23/Desktop/coding/Discord-bot-3/music.py", line 223, in offline
await self.functions.offline(ctx)
File "/home/liuk23/Desktop/coding/Discord-bot-3/funcitons.py", line 241, in offline
sys.exit(0)
SystemExit: 0
As you can notice, the Debug
text gets printed out, so the cog_unload
function get successfully called.
Although I am closing the loops, I get the Task was never retrieved
error. Am I misunderstanding the error?
Solution
From sys.exit
documentation:
Raise a SystemExit exception, signaling an intention to exit the interpreter.
What is happening is that the offline
task, by throwing SystemExit
, stops, but since no other task is awaiting on it, that exception is never retrieved.
The underlying problem is that, to quit the application, rather than throwing through sys.exit
, it would be better to stop the running loop cleanly. For example, if the loop was run with loop.run_until_complete(some_future)
, it's necessary to set that future with some_future.set_result(some_result)
.
Answered By - Ulisse Bordignon
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.