2

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?

halfer
  • 19,824
  • 17
  • 99
  • 186
DevSepp
  • 116
  • 1
  • 5
  • What about using [cron](https://en.wikipedia.org/wiki/Cron)? – iScripters Feb 09 '19 at 01:35
  • As far as I know I can only start an entire python process with corn, not a function. I have to load a tensorflow model later on, which takes time that I dont have in this scenario. So I'd like to load the Model and feed it the Data every minute. – DevSepp Feb 09 '19 at 01:39

2 Answers2

2

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))
Jab
  • 26,853
  • 21
  • 75
  • 114
  • Thx for the answer. The problem is that the API request takes some time, so I have this time + the 60 seconds which will drag the whole "schedule" behind (so I have 61 secs instead of 60 at every iteration), which leads to the problem that I do not meet the next full minute. – DevSepp Feb 09 '19 at 02:21
  • That shouldn't really matter much at all because every *roughly* 60 seconds you're getting the newest data, but if you insist I edited my answer with a way to do that. – Jab Feb 09 '19 at 02:49
0

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.

DevSepp
  • 116
  • 1
  • 5