0

I am pretty new with Async.io and I am using it with Discord.py to create a bot. Once a day, I need to update a spreadsheet, but the problem is that the spreadsheet has gotten a little long so it now triggers the loop's default timeout. Is there anyway to overcome this? I have seen run_until_complete but as you see below there is a await asyncio.sleep(86400) which from my understanding will not work with wait until complete because it will wait for a day? I would also be fine with just changing the timeout for that function and then changing it back after it is complete, but I have not been able to find any resources.

Here is the function that needs to repeat everyday:

async def updateSheet():
    while True:
        print("Updating Sheet at " + datetime.now().strftime("%H:%M"))
        
        user.updateAllUsers(os.getenv('CID'), os.getenv('CS'), subs) #This is the function that takes too long
        
        print("Done Updating")
        await asyncio.sleep(86400)

and here is how I am adding it to the loop (because I am using Discord.py):

@client.event
async def on_ready():
    print('We have logged in as {0.user}'.format(client))
    client.loop.create_task(updateSheet())

Any and all help will be appreciated since as long as this is down my project loses precious time. :)

Jared Cohen
  • 195
  • 1
  • 1
  • 11

2 Answers2

0

If something is blocking, the direct method would be trying to convert it to a task, which might not be possible in your case. So we would have to use something like APS to schedule jobs.

sched = Scheduler()
sched.start()
@sched.cron_schedule(day='mon-fri')
def task():
    user.updateAllUsers(os.getenv('CID'), os.getenv('CS'), subs)

Make sure you do this in a separate file, and use async scheduler for tasks.

Ceres
  • 2,200
  • 1
  • 6
  • 22
  • Hi thank you for the quick response. I kind of need this to block since it is doing actions on a spreadsheet that other parts of the code also do actions on. So basically I would need the loop once a day to stop and update the spreadsheet. And when you say to do it in a separate file what do you mean? I’m not exactly sure how to implement your answer. Thanks :) – Jared Cohen May 14 '21 at 18:31
  • The block would still exist if the file is being updated from anywhere, I asked you to put this in a separate file as you cannot run a discord bot and run other function as `bot.run` is blocking – Ceres May 15 '21 at 05:06
0

You can simply measure how much time does the function take to execute and simply subtract it from 86400

import time

async def updateSheet():
    while True:
        start = time.monotonic()
        print("Updating Sheet at " + datetime.now().strftime("%H:%M"))
        
        user.updateAllUsers(os.getenv('CID'), os.getenv('CS'), subs) #This is the function that takes too long

        end = time.monotonic()
        total = end - start
        sleep_time = 86400 - total
        await asyncio.sleep(sleep_time)

I really suggest you that you run the blocking functions in a non-blocking way, refer to one of my previous answers for more info, (What does "blocking" mean)

Łukasz Kwieciński
  • 13,310
  • 3
  • 17
  • 33
  • Hi Thanks for the answer, the issue is that while updating the sheet (calling updateAllUsers), it stops in the middle with an `asyncio.TimeoutError.` So I don't think this would solve my problem. – Jared Cohen May 14 '21 at 20:55
  • I think it would help if you simply call the function inside a try/except block, also this isn’t really related with your question – Łukasz Kwieciński May 14 '21 at 21:02