Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Schedule Asyncio task to execute every X seconds?

I'm trying to create a python discord bot that will check active members every X seconds, and award members with points for their time online. I'm using asyncio to handle the chat commands and that is all working. My issue is finding a way to schedule this checking of active members every X seconds with async

I've read the asnycio documentation but this is my first time working with it and I'm having a hard time wrapping my head around tasks and loops and co routines and etc.

@client.event
async def on_message(message):

    # !gamble command
    if message.content.startswith('!gamble'):

        ...code that works....

    # !help command
    elif message.content == '!help':

         ...code that works....

    # !balance command
    elif message.content == '!balance':

      ...code that works....

@client.event
async def on_ready():
    print('Logged in as')
    print(client.user.name)
    print(client.user.id)
    print('------')

# Do this every X seconds to give online users +1 points
async def periodic_task():
      TODO

My goal is to have the bot be able to handle commands given to it through chat, while also triggering a function every X seconds unrelated to chat commands or events in the Discord server. I know how to make the code inside the function achieve my goal, just not how to trigger it

like image 354
Logman Avatar asked Jan 11 '19 20:01

Logman


1 Answers

If you want to make sure the execution time doesn't cause drift in the intervals, you can use asyncio.gather.

import asyncio, time, random


start_time = time.time()


async def stuff():
    await asyncio.sleep(random.random() * 3)
    print(round(time.time() - start_time, 1), "Finished doing stuff")


async def do_stuff_periodically(interval, periodic_function):
    while True:
        print(round(time.time() - start_time, 1), "Starting periodic function")
        await asyncio.gather(
            asyncio.sleep(interval),
            periodic_function(),
        )


asyncio.run(do_stuff_periodically(5, stuff))

The output then becomes:

0.0 Starting periodic function
0.5 Finished doing stuff
5.0 Starting periodic function
7.2 Finished doing stuff
10.0 Starting periodic function
10.1 Finished doing stuff
15.0 Starting periodic function
17.9 Finished doing stuff

As you can see the execution time of the periodic function called doesn't affect the start time of the new interval.

like image 91
marcoc88 Avatar answered Oct 22 '22 14:10

marcoc88