只需睡10秒或使用threading.Timer(10,foo)会导致启动时间漂移。(你可能不在乎这一点,或者它可能是一个重要的问题来源,取决于你的确切情况。)造成这种情况的原因有两个-线程的唤醒时间或函数的执行时间不准确。
您可以在这篇文章的末尾看到一些结果,但首先是一个如何修复它的示例。您需要跟踪您的函数下一次调用的时间,而不是它实际被调用的时间,并说明不同之处。
这里有一个稍微偏移的版本:
import datetime, threading
def foo():
print datetime.datetime.now()
threading.Timer(1, foo).start()
foo()
其输出如下:
2013-08-12 13:05:36.483580
2013-08-12 13:05:37.484931
2013-08-12 13:05:38.485505
2013-08-12 13:05:39.486945
2013-08-12 13:05:40.488386
2013-08-12 13:05:41.489819
2013-08-12 13:05:42.491202
2013-08-12 13:05:43.492486
2013-08-12 13:05:44.493865
2013-08-12 13:05:45.494987
2013-08-12 13:05:46.496479
2013-08-12 13:05:47.497824
2013-08-12 13:05:48.499286
2013-08-12 13:05:49.500232
你可以看到,亚秒计数不断增加,因此,开始时间是“漂移”。
这是正确解释漂移的代码:
import datetime, threading, time
next_call = time.time()
def foo():
global next_call
print datetime.datetime.now()
next_call = next_call+1
threading.Timer( next_call - time.time(), foo ).start()
foo()
其输出如下:
2013-08-12 13:21:45.292565
2013-08-12 13:21:47.293000
2013-08-12 13:21:48.293939
2013-08-12 13:21:49.293327
2013-08-12 13:21:50.293883
2013-08-12 13:21:51.293070
2013-08-12 13:21:52.293393
在这里,你可以看到,不再有任何增加的亚秒的倍。
如果您的事件确实经常发生,您可能希望在单个线程中运行计时器,而不是为每个事件启动一个新线程。在考虑漂移的同时,这看起来是这样的:
import datetime, threading, time
def foo():
next_call = time.time()
while True:
print datetime.datetime.now()
next_call = next_call+1;
time.sleep(next_call - time.time())
timerThread = threading.Thread(target=foo)
timerThread.start()
但是您的应用程序不会正常退出,您需要关闭计时器线程。如果要在完成应用程序时正常退出,而不手动关闭线程,则应使用
timerThread = threading.Thread(target=foo)
timerThread.daemon = True
timerThread.start()