2013-05-06 267 views
2

我一直試圖在Python中做一個精確的計時器,或者如同操作系統允許的那樣精確。但它的接縫比我最初想象的要複雜。定時器中斷線程python

這是我想它是如何工作的:

from time import sleep 
from threading import Timer 

def do_this(): 
    print ("hello, world") 


t = Timer(4, do_this) 
t.start() 
sleep(20) 
t.cancel() 

凡在20秒我將執行「do_this」每四秒。然而,'do_this'會執行一次,然後腳本會在20秒後終止。

另一種方法是用while循環創建一個thred。

import time 
import threading 
import datetime 

shutdown_event = threading.Event() 

def dowork(): 
    while not shutdown_event.is_set(): 
     print(datetime.datetime.now()) 
     time.sleep(1.0) 

def main(): 

    t = threading.Thread(target=dowork, args=(), name='worker') 
    t.start() 

    print("Instance started") 

    try: 
     while t.isAlive(): 
      t.join(timeout=1.0) 
    except (KeyboardInterrupt, SystemExit): 
      shutdown_event.set() 
    pass 

if __name__ == '__main__': 
    main() 

這個線程按預期執行,但我得到一個時間漂移。在這種情況下,我必須通過相應地調整睡眠來補償在while循環中執行代碼所需的時間。

有沒有一種簡單的方法在Python中執行計時器每秒(或任何間隔)而不引入漂移與系統時間相比,而不必補償sleep(n)參數?

感謝您的幫助,

/安德斯

回答

1

如果dowork()總是比你的間隔時間少運行,則可以產生一個新的線程,每4秒一個循環:

def dowork(): 
    wlen = random.random() 
    sleep(wlen) # Emulate doing some work 
    print 'work done in %0.2f seconds' % wlen 

def main(): 
    while 1: 
    t = threading.Thread(target=dowork) 
    time.sleep(4) 

如果dowork()可能會運行超過4秒,然後在您的主循環中,您要確保先前的作業在產生新作業之前完成。

但是,time.sleep()本身可能會漂移,因爲沒有保證線程實際掛起的時間。 正確的這樣做的方法是找出工作需要多長時間,並在餘下的時間間隔休眠。我認爲這是用戶界面和遊戲渲染引擎的工作原理,他們必須在固定時間顯示每秒固定幀數,並且渲染每個幀可能需要不同的時間長度才能完成。

+0

好的。謝謝。我也這麼想。爲了補償線程中代碼的執行時間,我會對代碼進行一些更改。 – 2013-05-08 10:02:00