python中斷time.sleep一種更優(yōu)雅的方式:event.wait
場景描述
實現(xiàn)一個功能,啟動一個線程,只要線程不中斷,就一直while true,間斷10s累加某個數(shù);
當(dāng)線程線程信號時,while停止,線程退出。
1、方法一 time.sleep
import time from threading import Thread class AddTask(Thread): def __init__(self): super().__init__() self.sum_num = 0 self._button = True def run(self): print('Begin to add ...') while self._button: print('Sleep start...') time.sleep(10) print('Sleep end...') self.sum_num += 10 print(f"Finish add, sum:{self.sum_num}...") def stop(self): print('Stop task...') self._button = False def do_main_task(): print('Do main task...') time.sleep(15) print('Finish main task...') return True if __name__ == '__main__': add_task = AddTask() add_task.start() main_task_end = do_main_task() if main_task_end: add_task.stop() time.sleep(1) print(f"sum: {add_task.sum_num}")
執(zhí)行結(jié)果:
Begin to add ...Do main task...
Sleep start...
Sleep end...
Sleep start...
Finish main task...
Stop task...
sum: 10
Sleep end...
Finish add,sum: 20...
解釋一下這段代碼的意思。在主線程里面,我調(diào)用do_main_task()
觸發(fā)了一個任務(wù)。這個任務(wù)執(zhí)行會久一些(這里設(shè)定15s)。但是這個任務(wù)完成以后,會有個返回值,告訴我完成了。另外創(chuàng)建一個 add_task 子線程,每10秒累加10。
但某些情況下,我不需要等待了,例如用戶主動取消了任務(wù)。這個時候,我就想提前結(jié)束這個 add_task 子線程。
通過執(zhí)行結(jié)果可以看出,當(dāng)執(zhí)行一次+10,等待10s后,又過了5秒,主線程do_main_task結(jié)束了,這時add_task線程還在累加的sleep(10)中沒有退出。主線程執(zhí)行結(jié)果已經(jīng)是sum=10,再過5秒后add_task線程才結(jié)束。
但是,線程是不能從外面主動殺死的,只能讓它自己退出。
2、方法二 event.wait
應(yīng)用threading
模塊里面的Event
用法和sleep差不多:
import threading event = threading.Event() event.wait(5)
上述例子可以這樣實現(xiàn):
import time from threading import Thread from threading import Event class AddTask(Thread): def __init__(self): super().__init__() self.sum_num = 0 self.event = Event() def run(self): print('Begin to add ...') while not self.event.is_set(): print('Sleep start...') self.event.wait(10) print('Sleep end...') self.sum_num += 10 print(f"Finish add, sum:{self.sum_num}...") def stop(self): print('Stop task...') self.event.set() def do_main_task(): print('Do main task...') time.sleep(15) print('Finish main task...') return True if __name__ == '__main__': add_task = AddTask() add_task.start() main_task_end = do_main_task() if main_task_end: add_task.stop() time.sleep(1) print(f"sum: {add_task.sum_num}")
執(zhí)行結(jié)果:
Do main task...
Begin to add ...
Sleep start...
Sleep end...
Sleep start...
Finish main task...
Stop task...
Sleep end...
Finish add, sum:20...sum: 20
當(dāng)執(zhí)行event.set()
后,子線程里面self.event.is_set()
就會返回 False,于是這個循環(huán)就不會繼續(xù)執(zhí)行了。
即使self.event.wait(10)
剛剛開始阻塞,只要我在主線程中執(zhí)行了event.set()
,子線程里面的阻塞立刻就會結(jié)束。
于是子線程立刻就會結(jié)束。不需要再白白等待10秒。
并且,event.wait()
這個函數(shù)在底層是使用 C 語言實現(xiàn)的,不受 GIL 鎖的干擾。
總結(jié)
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
非常詳細(xì)的Django連接mysql數(shù)據(jù)庫步驟記錄
我的Mysql中已經(jīng)有了項目需要使用的相關(guān)數(shù)據(jù)庫,現(xiàn)在需要通過django來獲取Mysql里的數(shù)據(jù)并使用,下面這篇文章主要給大家介紹了關(guān)于非常詳細(xì)的Django連接mysql數(shù)據(jù)庫步驟,需要的朋友可以參考下2022-10-10手把手教你利用opencv實現(xiàn)人臉識別功能(附源碼+文檔)
最近搞一個人臉識別的項目練練手,不得不感嘆opencv做人臉檢測實在是強,這篇文章主要給大家介紹了關(guān)于利用opencv實現(xiàn)人臉識別功能的相關(guān)資料,并附上了源碼以及文檔,需要的朋友可以參考下2021-09-09Python使用matplotlib繪圖無法顯示中文問題的解決方法
這篇文章主要介紹了Python使用matplotlib繪圖無法顯示中文問題的解決方法,結(jié)合具體實例形式分析了Python使用matplotlib繪圖時出現(xiàn)中文亂碼的原因與相關(guān)解決方法,需要的朋友可以參考下2018-03-03python在ubuntu中的幾種安裝方法(小結(jié))
本篇文章主要介紹了python在ubuntu中的幾種安裝方法(小結(jié)),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-12-12詳解在OpenCV中實現(xiàn)的圖像標(biāo)注技術(shù)
圖像標(biāo)注在計算機(jī)視覺中很重要,計算機(jī)視覺是一種技術(shù),它允許計算機(jī)從數(shù)字圖像或視頻中獲得高水平的理解力,并以人類的方式觀察和解釋視覺信息,本文將重點討論在OpenCV的幫助下創(chuàng)建這些注釋,感興趣的朋友一起看看吧2022-06-06Python使用smtp和pop簡單收發(fā)郵件完整實例
這篇文章主要介紹了Python使用smtp和pop簡單收發(fā)郵件完整實例,簡單介紹了smtp和pop,然后分享了相關(guān)實例代碼,具有一定借鑒價值,需要的朋友可以參考下2018-01-01