摘要:更循環定時器這里有更的方法重點研究類,它繼承了,但是重寫了父類的方法。再看看類中的語句,直到才會退出循環,定時器才結束。我們知道定時器有一個方法可以提前取消操作。這樣便完成了一個還不錯的循環定時器。
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 的子類,而 Timer 只是 _Timer 類的工廠方法。
上面的代碼只會打印一次 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 秒輸出一個 hello, world。
達到效果了,但是這里面好像有點問題。回到 Timer 本身,它是一個 thread,每次循環間隔操作,系統都要創建一個線程,然后再回收,這對系統來說開銷很大。如果時間間隔 interval 很短,系統會一下子創建很多線程,這些線程很難快速回收,導致系統內存和cpu資源被消耗掉。
所以不提倡在 function 里繼續注冊一個 Timer。
這里有更 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 便不會繼續執行循環體了。這樣便完成了一個還不錯的循環定時器。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/43373.html
摘要:參數是要測試的代碼語句參數是運行代碼時需要的設置參數是一個定時器函數,與平臺有關。類中測試語句執行速度的對象方法。參數是測試代碼時的測試次數,默認為次。方法返回執行代碼的平均耗時,一個類型的秒數。 [TOC] 這里主要是算法的介紹以及一些判斷算法好壞的標準和方式 引入 如果a+b+c = 1000,且a^2 + b^2 = c^2,如何求出所有a,b,c可能的組合? 第一次嘗試: im...
摘要:上下文管理器協議包含和兩個方法。因此必要時在上下文管理器函數中使用語句防范錯誤。構建臨時忽略指定異常的上下文管理器。這是個基類,用于定義基于類的上下文管理器。塊結束時,按照后進先出的順序調用棧中各個上下文管理器的方法。 導語:本文章記錄了本人在學習Python基礎之控制流程篇的重點知識及個人心得,打算入門Python的朋友們可以來一起學習并交流。 本文重點: 1、掌握if語句之外的el...
摘要:二瀏覽器端在講解事件循環之前先談談中同步代碼異步代碼的執行流程。三端我自己認為的事件循環和瀏覽器端還是有點區別的,它的事件循環依靠引擎。四總結本篇主要介紹了瀏覽器和對于事件循環機制實現,由于能力水平有限,其中可能有誤之處歡迎指出。 一、前言 前幾天聽公司一個公司三年的前端說今天又學到了一個知識點-微任務、宏任務,我問他這是什么東西,由于在吃飯他淺淺的說了下,當時沒太理解就私下學習整理一...
閱讀 2214·2021-11-25 09:43
閱讀 1178·2021-11-23 09:51
閱讀 3512·2021-11-23 09:51
閱讀 3638·2021-11-22 09:34
閱讀 1575·2021-10-09 09:43
閱讀 2136·2019-08-30 15:53
閱讀 3173·2019-08-30 14:07
閱讀 580·2019-08-28 18:14