python中斷time.sleep一種更優(yōu)雅的方式:event.wait
場景描述
實現(xiàn)一個功能,啟動一個線程,只要線程不中斷,就一直while true,間斷10s累加某個數(shù);
當線程線程信號時,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í)行結果:
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ā)了一個任務。這個任務執(zhí)行會久一些(這里設定15s)。但是這個任務完成以后,會有個返回值,告訴我完成了。另外創(chuàng)建一個 add_task 子線程,每10秒累加10。
但某些情況下,我不需要等待了,例如用戶主動取消了任務。這個時候,我就想提前結束這個 add_task 子線程。
通過執(zhí)行結果可以看出,當執(zhí)行一次+10,等待10s后,又過了5秒,主線程do_main_task結束了,這時add_task線程還在累加的sleep(10)中沒有退出。主線程執(zhí)行結果已經(jīng)是sum=10,再過5秒后add_task線程才結束。
但是,線程是不能從外面主動殺死的,只能讓它自己退出。
2、方法二 event.wait
應用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í)行結果:
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
當執(zhí)行event.set()后,子線程里面self.event.is_set()就會返回 False,于是這個循環(huán)就不會繼續(xù)執(zhí)行了。
即使self.event.wait(10)剛剛開始阻塞,只要我在主線程中執(zhí)行了event.set(),子線程里面的阻塞立刻就會結束。
于是子線程立刻就會結束。不需要再白白等待10秒。
并且,event.wait()這個函數(shù)在底層是使用 C 語言實現(xiàn)的,不受 GIL 鎖的干擾。
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
非常詳細的Django連接mysql數(shù)據(jù)庫步驟記錄
我的Mysql中已經(jīng)有了項目需要使用的相關數(shù)據(jù)庫,現(xiàn)在需要通過django來獲取Mysql里的數(shù)據(jù)并使用,下面這篇文章主要給大家介紹了關于非常詳細的Django連接mysql數(shù)據(jù)庫步驟,需要的朋友可以參考下2022-10-10
手把手教你利用opencv實現(xiàn)人臉識別功能(附源碼+文檔)
最近搞一個人臉識別的項目練練手,不得不感嘆opencv做人臉檢測實在是強,這篇文章主要給大家介紹了關于利用opencv實現(xiàn)人臉識別功能的相關資料,并附上了源碼以及文檔,需要的朋友可以參考下2021-09-09
Python使用matplotlib繪圖無法顯示中文問題的解決方法
這篇文章主要介紹了Python使用matplotlib繪圖無法顯示中文問題的解決方法,結合具體實例形式分析了Python使用matplotlib繪圖時出現(xiàn)中文亂碼的原因與相關解決方法,需要的朋友可以參考下2018-03-03
Python使用smtp和pop簡單收發(fā)郵件完整實例
這篇文章主要介紹了Python使用smtp和pop簡單收發(fā)郵件完整實例,簡單介紹了smtp和pop,然后分享了相關實例代碼,具有一定借鑒價值,需要的朋友可以參考下2018-01-01

