datetime.utcnow().second
我希望在零时每分钟执行一次循环。到目前为止我有这个
while True:
while datetime.utcnow().second != 0: pass
do_something()
但问题是我在浪费 cpu 进程。我会使用time.sleep(60)
,但我不知道它如何与 UTC 时钟同步,因为time.sleep(60)
随着时间的推移可能会偏离官方的 UTC 时间。
我能想到的最好方法是睡到下一分钟:
while True:
sleeptime = 60 - datetime.utcnow().second
time.sleep(sleeptime)
...
如果你想非常精确:
while True:
t = datetime.utcnow()
sleeptime = 60 - (t.second + t.microsecond/1000000.0)
time.sleep(sleeptime)
...
这会以亚秒级精度准确地休眠到达下一分钟所需的时间。
编辑修复分钟翻转错误。
有趣的问题 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
>>>
有趣的是,它似乎非常准确,可能由于执行实际指令所需的时间而产生了轻微的开销,我想如果我们想要完美的准确性,我们需要考虑它们......
天真的方法过于将 更改pass
为 a sleep (1)
,这将大大减轻 CPU 压力,但如果由于某种原因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
。换句话说,当我们进入下一分钟时。
通过这样做而不是尝试检测零秒,您还可以绕过错过一分钟的可能性。
而且,如果您想确保尽可能接近分钟翻转,您可以将 替换sleep (1)
为pass
. 这样,您将在 60 秒(平均 5%)中以全 CPU 运行最多三秒(平均 5%),并尽可能接近分钟翻转。
当我执行那个小修改时,我得到:
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