How to synchronize a loop with a UTC timer and execute every new minute?

I want the loop to execute once every minute when it datetime.utcnow().secondis zero. While I have it

while True:
    while datetime.utcnow().second != 0: pass
    do_something()

But the problem is that I am losing processor processes. I would use it time.sleep(60), but I do not know how it will synchronize with the UTC clock, because it time.sleep(60)may deviate from the official UTC time over time.

+5
source share
4 answers

The best way I can think of is to sleep until the next minute:

while True:
    sleeptime = 60 - datetime.utcnow().second
    time.sleep(sleeptime)
    ...

If you want to be very precise:

while True:
    t = datetime.utcnow()
    sleeptime = 60 - (t.second + t.microsecond/1000000.0)
    time.sleep(sleeptime)
    ...

This is a sleeping, even period of time necessary to reach the next minute to the nearest second.

EDITED fix the minute rollover error.

+11

python , sched, , ...

.

>>> import sched, time, datetime
>>> sch = sched.scheduler(time.time, time.sleep)
>>> 
>>> count = 0
>>> last = 0
>>> def do_something():
...     global count, last
...     if count != 5:
...         sch.enter(5, 1, do_something, ())
...     print datetime.datetime.now() - last
...     last = datetime.datetime.now()
...     count += 1
... 
>>> sch.enter(5, 1, do_something, ())
Event(time=1345872167.9454501, priority=1, action=<function do_something at 0x1004c4a28>, argument=())
>>> last = datetime.datetime.now()
>>> sch.run()

0:00:05.000015
0:00:05.000159
0:00:05.000184
0:00:05.000183
0:00:05.000181
0:00:05.000148
>>>

, , , , - , , , , ...

+1

pass sleep (1), , , - 12:30:59.99999, 12:31:01.00001.

. , , . .

- Python , :

from datetime import datetime
from time import sleep

def WaitForNextMinute():
    secs = datetime.utcnow().second
    while secs < 57:
        sleep (57 - secs)
        secs = datetime.utcnow().second
    while datetime.utcnow().second >= 57:
        sleep (1)

while True:
    WaitForNextMinute()
    print datetime.utcnow()

:

2012-08-25 04:16:00.111257
2012-08-25 04:17:00.157155
2012-08-25 04:18:00.217356
2012-08-25 04:19:00.270348
2012-08-25 04:20:00.330203
2012-08-25 04:21:00.390318
2012-08-25 04:22:00.450440
2012-08-25 04:23:00.510491
2012-08-25 04:24:00.570487
2012-08-25 04:25:00.630502
2012-08-25 04:26:00.690523
2012-08-25 04:27:00.750642
2012-08-25 04:28:00.810780
2012-08-25 04:29:00.870900
2012-08-25 04:30:00.931078

, .

, , , .

, , , 12:21:13. secs , 57, 57 - 13 , 12:21:57.

, second 57. , .

, , , .

And if you want you to get as close as possible to the minute survey, you can replace sleep (1)with pass. Thus, you will work with a full CPU rollback for no more than three seconds out of sixty (an average of 5%) and get as close as possible to a minute rollover.

When I do this small modification, I get:

2012-08-25 05:48:00.000003
2012-08-25 05:49:00.000003
2012-08-25 05:50:00.000003
2012-08-25 05:51:00.000004
2012-08-25 05:52:00.000004
2012-08-25 05:53:00.000004
2012-08-25 05:54:00.000003
2012-08-25 05:55:00.000004
0
source

It is possible to use the upscaler. Same as cron, but more flexible. https://apscheduler.readthedocs.io/en/latest/

0
source

All Articles