溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

threading線程模塊怎么在Python中使用

發(fā)布時間:2021-03-18 16:44:57 來源:億速云 閱讀:119 作者:Leah 欄目:開發(fā)技術

這篇文章給大家介紹threading線程模塊怎么在Python中使用,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

threading-更高級別的線程接口

該模塊在較低級別thread模塊之上構建更高級別的線程接口。另請參見mutex和Queue模塊。

該dummy_threading模塊適用于threading因thread缺失而無法使用的情況 。

注意: 從Python 2.6開始,該模塊提供 符合 PEP 8的別名和屬性,以替換camelCase受Java的線程API啟發(fā)的名稱。此更新的API與multiprocessing模塊的API兼容 。但是,沒有為camelCase名稱的棄用設置計劃,它們在Python 2.x和3.x中仍然完全受支持。


注意 :從Python 2.5開始,幾個Thread方法引發(fā)RuntimeError 而不是AssertionError錯誤地調用。

該模塊定義了以下功能和對象:

threading.active_count()
threading.activeCount()
返回Thread當前活動的對象數。返回的計數等于返回的列表的長度enumerate()。

在2.6版中更改:添加了active_count()拼寫。

threading.Condition()
返回新條件變量對象的工廠函數。條件變量允許一個或多個線程等待,直到另一個線程通知它們。

請參閱條件對象。

threading.current_thread()
threading.currentThread()
返回當前Thread對象,對應于調用者的控制線程。如果未通過threading模塊創(chuàng)建調用者的控制 線程,則返回具有有限功能的虛擬線程對象。

在2.6版中更改:添加了current_thread()拼寫。

threading.enumerate()
返回Thread當前活動的所有對象的列表。該列表包括守護線程,由其創(chuàng)建的虛擬線程對象 current_thread()和主線程。它排除了尚未啟動的已終止線程和線程。

threading.Event()
返回新事件對象的工廠函數。事件管理一個標志,該標志可以使用該set()方法設置為true,并使用該方法重置為false clear()。該wait()方法將阻塞,直到該標志為真。

請參閱事件對象。

類threading.local
表示線程局部數據的類。線程局部數據是其值是線程特定的數據。要管理線程本地數據,只需創(chuàng)建一個local(或子類)實例并在其上存儲屬性:

mydata = threading.local()
mydata.x = 1

對于單獨的線程,實例的值將不同。

有關更多詳細信息和大量示例,請參閱_threading_local模塊的文檔字符串 。

版本2.4中的新功能。

threading.Lock()
返回新原始鎖定對象的工廠函數。一旦線程獲得它,后續(xù)嘗試獲取它就會阻塞,直到它被釋放; 任何線程都可以釋放它。

請參見鎖定對象。

threading.RLock()
返回新的可重入鎖定對象的工廠函數。必須由獲取它的線程釋放重入鎖。一旦線程獲得了可重入鎖,同一個線程可以再次獲取它而不會阻塞; 線程必須在每次獲取它時釋放一次。

請參閱RLock對象。

threading.Semaphore([ 值] )
返回新信號量對象的工廠函數。信號量管理一個計數器,表示release()呼叫數減去acquire()呼叫數 加上初始值。該acquire()方法在必要時阻止,直到它可以返回而不使計數器為負。如果沒有給出,則值默認為1。

請參見信號量對象。

threading.BoundedSemaphore([ 值] )
返回新的有界信號量對象的工廠函數。有界信號量檢查以確保其當前值不超過其初始值。如果確實如此,ValueError則被提出。在大多數情況下,信號量用于保護容量有限的資源。如果信號量被釋放太多次,則表明存在錯誤。如果沒有給出,則值默認為1。

類 threading.Thread
表示控制線程的類。該類可以以有限的方式安全地進行子類化。

請參見線程對象。

類 threading.Timer
在指定的時間間隔過后執(zhí)行函數的線程。

見Timer對象。

threading.settrace(func )
為從threading模塊啟動的所有線程設置跟蹤功能。在調用sys.settrace()其run()方法之前,將為每個線程 傳遞 func。

版本2.3中的新功能。

threading.setprofile(func )
為從threading模塊啟動的所有線程設置配置文件功能。在調用sys.setprofile()其run()方法之前,將為每個線程 傳遞 func。

版本2.3中的新功能。

threading.stack_size([ 大小] )
返回創(chuàng)建新線程時使用的線程堆棧大小。可選的 size參數指定用于后續(xù)創(chuàng)建的線程的堆棧大小,并且必須為0(使用平臺或已配置的默認值)或至少為32,768(32 KiB)的正整數值。如果未指定size,則使用0。如果不支持更改線程堆棧大小,ThreadError則引發(fā)a。如果指定的堆棧大小無效,則aValueError被提升,堆棧大小未經修改。32kB是目前支持的最小堆棧大小值,以保證解釋器本身有足夠的堆??臻g。請注意,某些平臺可能對堆棧大小的值有特定限制,例如要求最小堆棧大小> 32kB或需要以系統內存頁面大小的倍數進行分配 - 應提供平臺文檔以獲取更多信息(4kB頁面是常見的;在沒有更具體的信息的情況下,建議的方法是使用4096的倍數作為堆棧大小??捎眯裕篧indows,具有POSIX線程的系統。

2.5版中的新功能。

異常threading.ThreadError
針對各種與線程相關的錯誤提出,如下所述。請注意,許多接口使用RuntimeError而不是ThreadError。

下面記錄了對象的詳細界面。

該模塊的設計基于Java的線程模型。但是,在Java使鎖和條件變量成為每個對象的基本行為的地方,它們是Python中的獨立對象。Python的Thread類支持Java的Thread類的行為的子集; 目前,沒有優(yōu)先級,沒有線程組,線程不能被銷毀,停止,暫停,恢復或中斷。Java的Thread類的靜態(tài)方法在實現時會映射到模塊級函數。

下面描述的所有方法都是原子執(zhí)行的。

線程對象

此類表示在單獨的控制線程中運行的活動。有兩種方法可以指定活動:將可調用對象傳遞給構造函數,或者通過覆蓋run()子類中的方法。不應在子類中重寫其他方法(構造函數除外)。換句話說, 只 覆蓋此類的init()和run()方法。

創(chuàng)建線程對象后,必須通過調用線程的start()方法啟動其活動。這將run()在單獨的控制線程中調用該方法。

一旦線程的活動開始,線程就被認為是“活著的”。當它的run()方法終止時,它會停止活動- 通常,或者通過引發(fā)未處理的異常。該is_alive()方法測試線程是否存活。

其他線程可以調用線程的join()方法。這會阻塞調用線程,直到調用其join()方法的線程終止。

線程有一個名字。名稱可以傳遞給構造函數,并通過name屬性讀取或更改。

線程可以標記為“守護程序線程”。這個標志的意義在于當只剩下守護進程線程時整個Python程序退出。初始值繼承自創(chuàng)建線程。可以通過daemon酒店設置標志。

注意:守護程序線程在關閉時突然停止。他們的資源(例如打開文件,數據庫事務等)可能無法正確發(fā)布。如果您希望線程正常停止,請使它們成為非守護進程并使用合適的信令機制,例如Event。

有一個“主線程”對象; 這對應于Python程序中的初始控制線程。它不是守護程序線程。

有可能創(chuàng)建“虛擬線程對象”。這些是與“外部線程”相對應的線程對象,它們是在線程模塊外部啟動的控制線程,例如直接來自C代碼。虛擬線程對象具有有限的功能; 他們總是被認為是活著的和守護的,不能被join()編輯。它們永遠不會被刪除,因為無法檢測外來線程的終止。

class threading.Thread(group = None,target = None,name = None,args =(),kwargs = {} )
應始終使用關鍵字參數調用此構造函數。參數是:

小組應該None; 在實現ThreadGroup類時為將來的擴展保留 。

target是run()方法調用的可調用對象。默認為None,意味著什么都沒有被調用。

name是線程名稱。默認情況下,唯一名稱由“Thread- N ” 形式構成,其中N是小十進制數。

args是目標調用的參數元組。默認為()。

kwargs是目標調用的關鍵字參數字典。默認為{}。

如果子類重寫構造函數,則必須確保Thread.init()在對線程執(zhí)行任何其他操作之前調用基類構造函數()。
start()
開始線程的活動。

每個線程對象最多只能調用一次。它安排run()在單獨的控制線程中調用對象的方法。

此方法將RuntimeError在同一個線程對象上多次調用if。

run()
表示線程活動的方法。

您可以在子類中重寫此方法。標準run() 方法調用傳遞給對象構造函數的可調用對象作為目標參數(如果有),分別使用args和kwargs參數中的順序和關鍵字參數。

join([ 超時] )
等到線程終止。這將阻塞調用線程,直到調用其join()方法的線程終止 - 正常或通過未處理的異常 - 或直到發(fā)生可選的超時。

當超時參數存在而不存在時None,它應該是一個浮點數,指定操作的超時(以秒為單位)(或其中的分數)。由于join()總是返回None,必須調用isAlive()后join()決定超時是否發(fā)生了-如果線程還活著時,join()調用超時。

當timeout參數不存在時None,操作將阻塞,直到線程終止。

線程可以join()多次編輯。

join()提出了RuntimeError如果試圖加入當前線程因為這將導致死鎖。join()在線程啟動之前它也是一個錯誤, 并且嘗試這樣做會引發(fā)相同的異常。

name
字符串僅用于識別目的。它沒有語義。多個線程可以賦予相同的名稱。初始名稱由構造函數設置。

版本2.6中的新功能。

getName()
setName()
適用于2.6之前的API name。

ident
此線程的“線程標識符”或者None線程尚未啟動。這是一個非零整數???thread.get_ident()功能。當線程退出并創(chuàng)建另一個線程時,可以回收線程標識符。即使在線程退出后,該標識符也可用。

版本2.6中的新功能。

is_alive()
isAlive()
返回線程是否存活。

此方法True在run()方法啟動之前返回,直到run()方法終止之后。模塊函數 enumerate()返回所有活動線程的列表。

在2.6版中更改:添加了is_alive()拼寫。

daemon
一個布爾值,指示此線程是否為守護程序線程(True)或不是(False)。必須在start()調用之前設置,否則RuntimeError引發(fā)。它的初始值繼承自創(chuàng)建線程; 主線程不是守護程序線程,因此在主線程中創(chuàng)建的所有線程都默認為daemon = False。

當沒有剩下活著的非守護進程線程時,整個Python程序退出。

版本2.6中的新功能。

isDaemon(
setDaemon()
適用于2.6之前的API daemon。

鎖定對象

原始鎖是一種同步原語,在鎖定時不屬于特定線程。在Python中,它是目前可用的最低級同步原語,由thread 擴展模塊直接實現。

原始鎖定處于“鎖定”或“解鎖”兩種狀態(tài)之一。它是在解鎖狀態(tài)下創(chuàng)建的。它有兩種基本方法,acquire()和 release()。當狀態(tài)解鎖時,acquire()將狀態(tài)更改為鎖定并立即返回。當狀態(tài)被鎖定時,acquire() 阻塞直到release()另一個線程中的調用將其更改為解鎖,然后該acquire()調用將其重置為已鎖定并返回。該 release()方法只應在鎖定狀態(tài)下調用; 它將狀態(tài)更改為已解鎖并立即返回。如果嘗試釋放未鎖定的鎖,ThreadError則會引發(fā)a。

當acquire()等待狀態(tài)轉為解鎖時阻塞多個線程時,只有一個線程在release()呼叫重置狀態(tài)解鎖時繼續(xù); 哪個等待線程繼續(xù)進行未定義,并且可能因實現而異。

所有方法都以原子方式執(zhí)行。

Lock.acquire([ 阻止] )
獲取鎖定,阻止或非阻止。

當阻塞參數設置為True(默認值)時調用,阻塞直到解鎖,然后將其設置為鎖定并返回True。

在使用阻塞參數設置為的情況下調用時False,請勿阻止。如果一個帶阻塞的調用設置為True阻塞,則False 立即返回; 否則,將鎖定設置為鎖定并返回True。

Lock.release()
解鎖。

鎖定鎖定后,將其重置為解鎖狀態(tài),然后返回。如果阻止任何其他線程等待鎖解鎖,則只允許其中一個繼續(xù)執(zhí)行。

在未鎖定的鎖上調用時,ThreadError會引發(fā)a。

沒有回報價值。

RLock對象

可重入鎖是同步原語,可以由同一線程多次獲取。在內部,除了原始鎖使用的鎖定/解鎖狀態(tài)之外,它還使用“擁有線程”和“遞歸級別”的概念。在鎖定狀態(tài)下,某些線程擁有鎖; 在解鎖狀態(tài)下,沒有線程擁有它。

要鎖定鎖,線程會調用其acquire()方法; 一旦線程擁有鎖,它就會返回。要解鎖鎖,線程會調用其 release()方法。acquire()/ release()call對可以嵌套; 只有最后一個release()(release()最外面的一對)重置鎖才能解鎖并允許另一個被阻塞的線程 acquire()繼續(xù)進行。

RLock.acquire([ blocking = 1 ] )
獲取鎖定,阻止或非阻止。

在不帶參數的情況下調用:如果此線程已擁有鎖,則將遞歸級別遞增1,并立即返回。否則,如果另一個線程擁有該鎖,則阻塞直到鎖被解鎖。鎖解鎖后(不屬于任何線程),然后獲取所有權,將遞歸級別設置為1,然后返回。如果多個線程被阻塞等待鎖解鎖,則一次只能有一個線程獲取鎖的所有權。在這種情況下沒有返回值。

在將blocking參數設置為true的情況下調用時,執(zhí)行與不帶參數調用時相同的操作,并返回true。

在將blocking參數設置為false的情況下調用時,請勿阻止。如果沒有參數的調用會阻塞,則立即返回false; 否則,執(zhí)行與不帶參數調用時相同的操作,并返回true。

RLock.release()
釋放鎖定,遞減遞歸級別。如果在遞減之后它為零,則將鎖重置為未鎖定(不由任何線程擁有),并且如果阻止任何其他線程等待鎖解鎖,則允許其中一個繼續(xù)進行。如果在遞減之后遞歸級別仍然非零,則鎖保持鎖定并由調用線程擁有。

僅在調用線程擁有鎖時調用此方法。RuntimeError如果在鎖定解鎖時調用此方法,則引發(fā)A.

沒有回報價值。

條件對象

條件變量總是與某種鎖相關聯; 這可以傳入,或者默認創(chuàng)建一個。(當多個條件變量必須共享同一個鎖時,傳入一個是有用的。)

條件變量具有acquire()與release()該調用相關聯的鎖的相應方法的方法。它還有一種wait() 方法notify()和notifyAll()方法。只有在調用線程獲得鎖定時才調用這三個,否則 RuntimeError引發(fā)a。

該wait()方法釋放鎖,然后阻塞,直到它被另一個線程中的相同條件變量喚醒notify()或notifyAll()調用。一旦被喚醒,它就會重新獲得鎖并返回。也可以指定超時。

該notify()方法喚醒等待條件變量的其中一個線程,如果有的話正在等待。該notifyAll()方法喚醒等待條件變量的所有線程。

注意:notify()和notifyAll()方法不釋放鎖; 這意味著被喚醒的一個或多個線程不會wait()立即從它們的調用返回,而是僅在調用notify()或notifyAll()最終放棄鎖的所有權的線程時 返回 。

提示:使用條件變量的典型編程風格使用鎖來同步對某些共享狀態(tài)的訪問; 對狀態(tài)的特定變化感興趣的線程wait()重復調用,直到它們看到所需的狀態(tài),而線程修改狀態(tài)調用notify()或者 notifyAll()當它們改變狀態(tài)時它可能是其中一個服務員的期望狀態(tài)。例如,以下代碼是具有無限緩沖區(qū)容量的通用生產者 - 消費者情況:

# Consume one item
cv.acquire()
while not an_item_is_available():
  cv.wait()
get_an_available_item()
cv.release()

# Produce one item
cv.acquire()
make_an_item_available()
cv.notify()
cv.release()

要在notify()和之間進行選擇notifyAll(),請考慮一個狀態(tài)更改是否只對一個或多個等待線程感興趣。例如,在典型的生產者 - 消費者情況下,向緩沖區(qū)添加一個項目只需要喚醒一個消費者線程。

class threading.Condition([ lock ] )
如果給出了lock參數None,則它必須是一個Lock 或RLock對象,并且它被用作底層鎖。否則,將RLock創(chuàng)建一個新對象并將其用作基礎鎖。

acquire(* args )
獲取底層鎖。此方法在底層鎖上調用相應的方法; 返回值是該方法返回的任何值。

release()
釋放底層鎖。此方法在底層鎖上調用相應的方法; 沒有回報價值。

wait([ 超時] )
等到通知或直到發(fā)生超時。如果在調用此方法時調用線程尚未獲取鎖定,RuntimeError則引發(fā)a。

此方法釋放底層鎖,然后阻塞,直到它被另一個線程中的相同條件變量喚醒notify()或notifyAll()調用,或者直到發(fā)生可選超時。一旦被喚醒或超時,它就會重新獲得鎖定并返回。

當超時參數存在而不存在時None,它應該是一個浮點數,指定操作的超時(以秒為單位)(或其中的分數)。

當底層鎖是a時RLock,它不會使用其release()方法釋放,因為當遞歸多次獲取鎖時,這實際上可能無法解鎖。相反,使用了RLock類的內部接口,即使多次遞歸獲取它也能真正解鎖它。然后,在重新獲取鎖時,使用另一個內部接口來恢復遞歸級別。

notify(n = 1 )
默認情況下,喚醒一個等待此條件的線程(如果有)。如果在調用此方法時調用線程尚未獲取鎖定, RuntimeError則引發(fā)a。

此方法最多喚醒等待條件變量的n個線程; 如果沒有線程在等待,那么這是一個無操作。

如果至少有n個 線程在等待,那么當前的實現只會喚醒n 個線程。但是,依靠這種行為是不安全的。未來的優(yōu)化實現有時可能會喚醒超過 n個線程。

注意:喚醒線程實際上不會從其wait() 調用返回,直到它可以重新獲取鎖定。由于notify()不釋放鎖,其調用者應該。

notify_all()
notifyAll()
喚醒等待這種情況的所有線程。這種方法就像 notify(),但喚醒所有等待的線程而不是一個。如果在調用此方法時調用線程尚未獲取鎖定, RuntimeError則引發(fā)a。

在2.6版中更改:添加了notify_all()拼寫。

信號量對象

這是計算機科學史上最古老的同步原語之一,由早期的荷蘭計算機科學家Edsger W. Dijkstra(他使用P()而V()不是acquire()和release())發(fā)明。

信號量管理一個內部計數器,該計數器按每次acquire()調用遞減并按每次 調用遞增release()。計數器永遠不會低于零; 當acquire()發(fā)現它為零時,它會阻塞,等待其他線程調用release()。

class threading.Semaphore([ value ] )
可選參數給出內部計數器的初始值 ; 它默認為1。如果給定的值小于0,ValueError則引發(fā)。

acquire([ 阻止] )
獲取信號量。

在不帶參數的情況下調用:如果內部計數器在輸入時大于零,則將其減1并立即返回。如果在進入時為零,則阻塞,等待其他線程調用 release()以使其大于零。這是通過適當的互鎖來完成的,這樣如果多個acquire()呼叫被阻止,它們 release()將完全喚醒其中一個。實現可以隨機選擇一個,因此不應該依賴被阻塞的線程被喚醒的順序。在這種情況下沒有返回值。

當使用blocking設置為true 調用時,執(zhí)行與不帶參數調用時相同的操作,并返回true。

當阻塞設置為false 時調用,請勿阻止。如果沒有參數的調用會阻塞,則立即返回false; 否則,執(zhí)行與不帶參數調用時相同的操作,并返回true。

release()
釋放信號量,將內部計數器遞增1。當它在進入時為零并且另一個線程正在等待它再次大于零時,喚醒該線程。

Semaphore示例

信號量通常用于保護容量有限的資源,例如數據庫服務器。在資源大小固定的任何情況下,您應該使用有界信號量。在產生任何工作線程之前,您的主線程將初始化信號量:

maxconnections = 5
...
pool_sema = BoundedSemaphore(value=maxconnections)

一旦產生,工作線程在需要連接到服務器時調用信號量的獲取和釋放方法:

pool_sema.acquire()
conn = connectdb()
... use connection ...
conn.close()
pool_sema.release()

有界信號量的使用減少了導致信號量被釋放的編程錯誤超過其獲取的編程錯誤的可能性。

事件對象

這是線程之間通信的最簡單機制之一:一個線程發(fā)出事件信號,其他線程等待它。

事件對象管理一個內部標志,該標志可以使用該set()方法設置為true,并使用該 方法重置為false clear() 。該wait()方法將阻塞,直到該標志為真。

類threading.Event
內部標志最初是假的。

is_set()
isSet()
當且僅當內部標志為真時返回true。

在2.6版中更改:添加了is_set()拼寫。

set()
將內部標志設置為true。等待它變?yōu)檎娴乃芯€程都被喚醒。wait()一旦標志為真,調用的線程將不會阻塞。

clear()
將內部標志重置為false。隨后,線程調用 wait()將阻塞,直到set()被調用以再次將內部標志設置為true。

wait([ 超時] )
阻止,直到內部標志為真。如果輸入時內部標志為真,則立即返回。否則,阻塞直到另一個線程調用 set()將標志設置為true,或者直到發(fā)生可選的超時。

當超時參數存在而不存在時None,它應該是一個浮點數,指定操作的超時(以秒為單位)(或其中的分數)。

此方法在退出時返回內部標志,因此它將始終返回, True除非給出超時并且操作超時。

在2.7版中更改:以前,該方法始終返回None。

定時器對象

此類表示應該在經過一定時間后運行的操作 - 計時器。 Timer是一個子類,Thread 因此也可以作為創(chuàng)建自定義線程的示例。

通過調用start() 方法,啟動計時器,就像使用線程一樣。通過調用cancel()方法可以停止計時器(在其動作開始之前) 。計時器在執(zhí)行其操作之前將等待的時間間隔可能與用戶指定的時間間隔不完全相同。

例如:

def hello():
  print "hello, world"

t = Timer(30.0, hello)
t.start() # after 30 seconds, "hello, world" will be printed

class threading.Timer(interval,function,args = [],kwargs = {} )
創(chuàng)建一個計時器,在經過間隔秒后,將使用參數args和關鍵字參數kwargs運行函數。

cancel()
停止計時器,取消執(zhí)行計時器的操作。這只有在計時器仍處于等待階段時才有效。

在with語句中使用鎖,條件和信號量

此模塊提供的具有acquire()和 release()方法的所有對象都可以用作with 語句的上下文管理器。acquire()進入塊時將調用該方法,并release()在退出塊時調用該方法。

目前Lock,RLock,Condition, Semaphore,和BoundedSemaphore對象可以用作 with聲明上下文管理。例如:

import threading

some_rlock = threading.RLock()

with some_rlock:
  print "some_rlock is locked while this executes"

在線程代碼中導入

雖然導入機制是線程安全的,但由于提供線程安全的方式存在固有限制,因此線程導入有兩個主要限制:

  • 首先,除了在主模塊中,導入不應該產生產生新線程然后以任何方式等待該線程的副作用。如果生成的線程直接或間接嘗試導入模塊,則不遵守此限制可能導致死鎖。

  • 其次,所有導入嘗試必須在解釋器開始關閉之前完成。僅通過從通過線程模塊創(chuàng)建的非守護程序線程執(zhí)行導入,可以最容易地實現這一點。直接使用線程模塊創(chuàng)建的守護程序線程和線程將需要一些其他形式的同步,以確保在系統關閉開始后它們不會嘗試導入。不遵守此限制將導致在解釋器關閉期間出現間歇性異常和崩潰(因為后期導入嘗試訪問不再處于有效狀態(tài)的機器)。

關于threading線程模塊怎么在Python中使用就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI