日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
除了time.sleep,你還有一個(gè)暫停代碼的方法

我們知道,在 Python 里面可以使用time.sleep來讓代碼暫停一段時(shí)間,例如:

 
 
 
  1. import time 
  2.  
  3. print('...部分代碼...') 
  4. time.sleep(5) 
  5. print('...剩下的代碼...') 

程序首先打印出...部分代碼...,然后等待5秒鐘,再打印出...剩下的代碼...。

現(xiàn)在大家想一想,有沒有什么辦法,在不使用time.sleep的情況下,讓程序暫停5秒?

你可能會(huì)說,用requests訪問一個(gè)延遲5秒的網(wǎng)址、或者用遞歸版算法計(jì)算斐波那契數(shù)列第36位……這些奇技淫巧。

不過今天我說的,是另外一個(gè)東西,threading模塊里面的Event。

我們來看看它的用法:

 
 
 
  1. import threading 
  2.  
  3. event = threading.Event() 
  4. print('...部分代碼...') 
  5. event.wait(5) 
  6. print('...剩下的代碼...') 

這樣一來,程序首先打印出...部分代碼...,然后等待5秒鐘,再打印出...剩下的代碼...。

功能看起來跟time.sleep沒什么區(qū)別,那為什么我要特別提到它呢?因?yàn)樵诙嗑€程里面,它比time.sleep更有用。我們來看一個(gè)例子:

 
 
 
  1. import threading 
  2.  
  3. class Checker(threading.Thread): 
  4.     def __init__(self, event): 
  5.         super().__init__() 
  6.         self.event = event 
  7.  
  8.     def run(self): 
  9.         while not self.event.is_set(): 
  10.             print('檢查 redis 是否有數(shù)據(jù)') 
  11.             time.sleep(60) 
  12.  
  13. trigger_async_task() 
  14. event = threading.Event() 
  15. checker = Checker(event) 
  16. checker.start() 
  17. if user_cancel_task(): 
  18.     event.set() 

我來解釋一下這段代碼的意思。在主線程里面,我調(diào)用trigger_async_task()觸發(fā)了一個(gè)異步任務(wù)。這個(gè)任務(wù)多久完成我并不清楚。但是這個(gè)任務(wù)完成以后,它會(huì)往 Redis 里面發(fā)送一條消息,只要 Redis 有這個(gè)消息了,我就知道它完成了。所以我要?jiǎng)?chuàng)建一個(gè) checker 子線程,每60秒去 Redis里面檢查任務(wù)是否完成。如果沒有完成,就暫停60秒,然后再檢查。

但某些情況下,我不需要等待了,例如用戶主動(dòng)取消了任務(wù)。這個(gè)時(shí)候,我就想提前結(jié)束這個(gè) checker 子線程。

但是我們知道,線程是不能從外面主動(dòng)殺死的,只能讓它自己退出。所以當(dāng)我執(zhí)行event.set()后,子線程里面self.event.is_set()就會(huì)返回 False,于是這個(gè)循環(huán)就不會(huì)繼續(xù)執(zhí)行了。

可是,如果某一輪循環(huán)剛剛開始,我在主線程里面調(diào)用了event.set()。此時(shí),子線程還在time.sleep中,那么子線程需要等待60秒才會(huì)退出。

但如果我修改一下代碼,使用self.event.wait(60):

 
 
 
  1. import threading 
  2.  
  3. class Checker(threading.Thread): 
  4.     def __init__(self, event): 
  5.         super().__init__() 
  6.         self.event = event 
  7.  
  8.     def run(self): 
  9.         while not self.event.is_set(): 
  10.             print('檢查 redis 是否有數(shù)據(jù)') 
  11.             self.event.wait(60) 
  12.  
  13. trigger_task() 
  14. event = threading.Event() 
  15. checker = Checker(event) 
  16. checker.start() 
  17. if user_cancel_task(): 
  18.     event.set() 

那么,即便self.event.wait(60)剛剛開始阻塞,只要我在主線程中執(zhí)行了event.set(),子線程里面的阻塞立刻就會(huì)結(jié)束。于是子線程立刻就會(huì)結(jié)束。不需要再白白等待60秒。

并且,event.wait()這個(gè)函數(shù)在底層是使用 C 語言實(shí)現(xiàn)的,不受 GIL 鎖的干擾。


本文名稱:除了time.sleep,你還有一個(gè)暫停代碼的方法
URL標(biāo)題:http://www.dlmjj.cn/article/dphsceg.html