Marcos Aguayo
Marcos Aguayo

Reputation: 7170

Python scripts that runs every minute without stoping

I have a Python script that sends a post request to my API every 1 minute:

while True:
    data = requests.post("URL_HERE", json={
        "api_key":"XXXX",
        "concat": 1,
        "messages": "HI"
    })
    time.sleep(60)

Everything works fine, but every 2 hours (more or less) there are 2 records of the same minute. Example:

2017-03-22 11:34:46.977255
2017-03-22 11:37:47.231694
2017-03-22 11:37:47.231694
2017-03-22 11:39:48.849003
2017-03-22 11:40:48.907895
...
2017-03-23 13:59:59.150108
2017-03-23 14:00:00.120431
2017-03-23 14:00:00.942033

I guess this is because the code inside the "while" takes a couple milliseconds to execute, thanks to that, one time every 2-3 hours a minute will have two records.

Anyone knows how can I fix this? I can't use cronjobs.

Maybe an asynchronous task?

And If I want this program to execute forever, It is okey to use a "while", or should I create a Daemon o something similar?

Upvotes: 4

Views: 1136

Answers (3)

Anton Panchishin
Anton Panchishin

Reputation: 3763

if you keep track of the time you can ensure you don't duplicate or have time drift.

here is an example

interval = 60
next = time.time() + interval

while True:
    if time.time() >= next :
        data = requests.post("URL_HERE", json={
            "api_key":"XXXX",
            "concat": 1,
            "messages": "HI"
        })
        next = next + interval
    time.sleep(next - time.time())

Upvotes: 1

Joakim
Joakim

Reputation: 195

Take a look at this post. Using a schedular might do the trick. Using that answer on your code will look somethig like this.

import sched, time, requests
schedul = sched.scheduler(time.time, time.sleep)

def send_post():
    data = requests.post("URL_HERE", json={
        "api_key": "XXXX",
        "concat": 1,
        "messages": "HI"
    })

schedul.enter(60, 1, send_post(), (schedul,))
schedul.run()  

Upvotes: 2

Nils Werner
Nils Werner

Reputation: 36765

Instead of waiting for 60 seconds you can wait the remaining number of seconds in the current minute:

time.sleep(60 - datetime.datetime.now().second)

If your job finishes late datetime.datetime.now().second will be 1 or 2 and you will wait 59 or 58 seconds.

Upvotes: 4

Related Questions