Devs11
Devs11

Reputation: 116

Call a python function on specific timestamps

I am trying to send a query to an API every full minute because the API updates its data every minute and I want the updated data immediately. It is important that the timing is very precise, I want to run everything continuously in the end.

This is vaguely what I am trying to do:

import time, sched

time = 1549667056000  # starting timestamp

def get_data():  # function to get some data from the API via requests
    #gets the Data

while true:
    s.scheduler(time)
    s.run(get_data())  # gets the data on the specified time(stamp)
    time = time + 60000  # adds 1 minute to the timestamp

Shall I do it this way, or is there a even smarter way of getting data from a REST Api exactly every full minute?

Upvotes: 2

Views: 1273

Answers (2)

Devs11
Devs11

Reputation: 116

Thanks to everyone for helping out.

This Answer worked for me pretty well in the end:

import time
starttime = time.time()
while True:
  print(time.time())
  time.sleep(60.0 - ((time.time() - starttime) % 60.0))

I let it run over night, there was no shift overtime. The time between the executions is exactly 60, no matter how long the code in the loop takes to execute.

Upvotes: 0

Jab
Jab

Reputation: 27515

You could use asyncio.sleep

For Python < 3.7

import asyncio

def get_data():
    print("Getting data")

async def main():
    while true:
        get_data()
        await asyncio.wait(MINUTE)

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

For Python 3.7+

import asyncio

def get_data():
    print("Getting data")

async def main():
    while true:
        get_data()
        await asyncio.wait(60)

#This is the only thing that changes
asyncio.run(main)

edit

As per your comment, if you're really worried about making sure this gets called every 60 seconds.

You could implement a way to take the time before get_data is called and subtract that from 60, just need to make sure if get_data does take over 60 secs to wait 0 secs or not at all.

Something like this for your main() should work:

#make sure to:
import time

async def main():
    while true:
        t = time.time()
        get_data()
        time_diff = int(time.time() - t)
        await asyncio.wait(max(60 - time_diff, 0))

Upvotes: 2

Related Questions