這篇文章帶給大家的內容是關於python實現循環定時器的方法介紹(附程式碼),有一定的參考價值,有需要的朋友可以參考一下,希望對你有所幫助。
python 如何寫一個定時器,循環定時要做某一操作呢?
Timer 物件
from threading import Timer def hello(): print "hello, world" t = Timer(10.0, hello) t.start()
10秒後輸出:
hello, world
重點研究 t = Timer(10.0, hello) 這句程式碼,python 提供了一個Timer 對象,它會在指定的時間後執行某一操作;它的完整形式:
class threading.Timer(interval, function, args=[], kwargs={})
interval 是時間間隔,function 是可呼叫的對象,args 和 kwargs 會作為 function 的參數。
注意:這裡只會執行一次 function,而不會一直定時執行,且 Timer 在執行操作的時候會建立一個新的執行緒。
Timer 在 python2 和 python3 有點區別:
# python2.7 def Timer(*args, **kwargs): return _Timer(*args, **kwargs) # python3.7 class Timer(Thread): pass
在 python3,Timer 是 Thread 的子類別;在 python2,_Timer 是 Thread 的子類,而Tim 只是工廠類型的方法Tim _Thread 的子類,而Tim 只是工廠的方法。
上面的程式碼只會列印一次 hello, world 後退出,那麼如何循環間隔列印呢?
粗糙的循環計時器
一種方法是在 function 裡繼續註冊一個Timer,這樣就可以在下一個 interval 繼續執行 function;
from threading import Timer def hello(): print "hello, world" Timer(10.0, hello) .start() t = Timer(10.0, hello) t.start()
每隔10 秒
每隔10 秒每隔10 秒
每隔10 秒輸出一個 hello, world。
達到效果了,但這裡面好像有點問題。回到 Timer 本身,它是一個 thread,每次循環間隔操作,系統都要創建一個線程,然後再回收,這對系統來說開銷很大。如果時間間隔 interval 很短,系統會一下子創建很多線程,這些線程很難快速回收,導致系統記憶體和cpu資源被消耗掉。
所以不主張在 function 裡繼續註冊一個 Timer。 更pythonic 循環定時器這裡有更pythonic 的方法:from threading import _Timer def hello(): print "hello, world" class RepeatingTimer(_Timer): def run(self): while not self.finished.is_set(): self.function(*self.args, **self.kwargs) self.finished.wait(self.interval) t = RepeatingTimer(10.0, hello) t.start()重點研究 RepeatingTimer 類,它繼承了 threading._Timer,但是重寫了父類的run 方法。這是 Python2 的寫法,python3 中 RepeatingTimer 應該要繼承 threading.Timer。 為什麼要重寫 Thread 的 run 方法? _Timer 是個 Thread 子類,我們先來看看 Thread 類別的 run 用法。
from threading import Thread def hello(): print "hello, world" # 继承 Thread class MyThread(Thread): # 把要执行的代码写到run函数里面 线程在创建后会直接运行run函数 def run(self): hello() t = MyThread() t.start()Thread 物件的完整定義:
class threading.Thread(group=None, target=None, name=None, args=(), kwargs={})其中 run 方法程式碼:
class Thread(_Verbose): def run(self): try: if self.__target: self.__target(*self.__args, **self.__kwargs) finally: # Avoid a refcycle if the thread is running a function with # an argument that has a member that points to the thread. del self.__target, self.__args, self.__kwargs標準的 run 方法用於執行使用者傳入建構函數的 target 方法。子類別可以重寫 run 方法,把要執行的程式碼寫到 run 裡面,執行緒在建立後,使用者呼叫 start() 方法會執行 run() 方法。 所以 RepeatingTimer 重寫 _Timer 的 run() 方法,可以改變執行緒的執行體,當我們呼叫 RepeatingTimer 的 start() 方法時會執行我們重寫的 run() 方法。 再看看 RepeatingTimer 類別中的 while not self.finished.is_set() 語句,self.finished.is_set() 直到 True 才會退出循環,計時器才會退出。 finished 是 threading.Event 物件。一個 Event 物件管理一個flag 標誌,它能被 set() 方法設定為True,也能被 clear() 方法設定為False,呼叫 wait([timeout]) 執行緒會一直sleep 到flag 為True 或逾時時間到達。 我們知道計時器有一個 cancel() 方法可以提前取消操作。它其實是呼叫 Event.clear() 方法提前讓 wait 方法結束等待,並且判斷在 flag 為 true 的情況下不執行定時器操作。特定的程式碼:###
class _Timer(Thread): """Call a function after a specified number of seconds: t = Timer(30.0, f, args=[], kwargs={}) t.start() t.cancel() # stop the timer's action if it's still waiting """ def __init__(self, interval, function, args=[], kwargs={}): Thread.__init__(self) self.interval = interval self.function = function self.args = args self.kwargs = kwargs self.finished = Event() def cancel(self): """Stop the timer if it hasn't finished yet""" self.finished.set() def run(self): self.finished.wait(self.interval) if not self.finished.is_set(): self.function(*self.args, **self.kwargs) self.finished.set()###所以 RepeatingTimer 的 run 方法會一直執行 while 循環體,在循環體了會執行使用者傳入的 function 對象,並等待指定的時間。當使用者想要退出計時器時,只要呼叫 cancel 方法,將 flag 置為 True 便不會繼續執行循環體了。這樣便完成了一個還不錯的循環定時器。 ###
以上是python實作循環定時器的方法介紹(附程式碼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!