Issue
I have experience in Python but this is my first time dealing with the asyncio
module. I'm making a matchmaking Discord bot using the discord.py
library, which uses asyncio
underneath.
What I'm trying to do is the following:
- The players register and set themselves as looking for a match
- Every 10 seconds the bot runs a coroutine that checks the player pool and creates a match between two of them.
- Every match is managed running a function, through private messages with the players. This function has to be asynchronous too because it interacts with Discord messages.
My problem is that I don't know how to launch the function for the matches (point 3) from the matchmaking loop (point 2) without awaiting for them in the loop.
If the loop calls the match function using await
the loop function stops running (which I understand). If I don't use await
it causes an error because the (asynchronous) function can't be run without awaiting for it.
I guess there is some way to start new coroutines, as it's how the events start running (I think), but I can't find it in the library documentation and I'd like to know the best practice within it.
This is more or less how the code looks:
import asyncio
import discord
import discord.ext.commands as commands
import discord.ext.tasks as tasks
bot = commands.Bot(command_prefix='!')
class LadderBot(commands.Cog):
@commands.Cog.listener()
async def on_ready(self):
self.matchmaking.start()
@tasks.loop(seconds=10.0)
async def matchmaking(self):
# take 2 players p1, p2 from pool
foo_starter(self.start_match(p1, p2))
async def start_match(self, p1, p2):
# Manage match through private messages
await foo_wait_for_result_from_players()
update_results_db()
Solution
Update 3: I think this actually answers MY question of how to get your task to run.... relinquish control back to the event loop
When is the task at `create_task()` executed in asyncio?
Update 2: so for what it's worth, it seems as though tasks WILL just go running without being awaited, if they are added with loop.create_task().
import asyncio
async def coro2():
print("coro2")
async def coro1():
loop = asyncio.get_running_loop()
task = loop.create_task(coro2())
print("created task")
return
async def main():
await coro1()
print("done with main")
if __name__ == "__main__":
loop = asyncio.get_event_loop()
loop.run_until_complete(main())
print("done with loop")
created task
done with main
coro2
done with loop
Update: The more I read your question the trickier I think it becomes. Tasks won't execute until they are awaited... now you can gather multiple tasks and await all of them at the same time using gather, but I don't think you can ever just arbitrarily add a task to the event loop and have it execute. At a certain point you must call await... and that call will stop that branch of execution (as you point out)
You are looking for Tasks.
Task = asyncio.create_task(some_coro)
Tasks are run in the event loop. You should look up some tutorials on how to create and run a task and ensure it has been completed.
First tutorial that came up. Seems to be fairly on point.
https://tutorialedge.net/python/concurrency/asyncio-tasks-tutorial/
Answered By - bravosierra99
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.