一、行程應用
1、multiprocessing模塊介紹
python中的多執行緒無法利用多核優勢,如果想要充分地使用多核CPU的資源(os.cpu_count()查看),在python中大部分情況需要使用多行程,Python提供了 multiprocessing,
multiprocessing模塊用來開啟子行程,并在子行程中執行我們定制的任務(比如函式),該模塊與多執行緒模塊threading的編程介面類似,
multiprocessing模塊的功能眾多:支持子行程、通信和共享資料、執行不同形式的同步,提供了Process、Queue、Pipe、Lock等組件,
需要再次強調的一點是:與執行緒不同,行程沒有任何共享狀態,行程修改的資料,改動僅限于該行程內,
2、Process類的介紹
創建行程的類:
Process([group [, target [, name [, args [, kwargs]]]]]),由該類實體化得到的物件,表示一個子行程中的任務(尚未啟動) 強調: 1. 需要使用關鍵字的方式來指定引數 2. args指定的為傳給target函式的位置引數,是一個元組形式,必須有逗號
引數介紹:
1 group引數未使用,值始終為None 2 target表示呼叫物件,即子行程要執行的任務 3 args表示呼叫物件的位置引數元組,args=(1,2,'egon',) 4 kwargs表示呼叫物件的字典,kwargs={'name':'egon','age':18} 5 name為子行程的名稱
方法介紹:
1 p.start():啟動行程,并呼叫該子行程中的p.run() 2 p.run():行程啟動時運行的方法,正是它去呼叫target指定的函式,我們自定義類的類中一定要實作該方法 3 p.terminate():強制終止行程p,不會進行任何清理操作,如果p創建了子行程,該子行程就成了僵尸行程,使用該方法需要特別小心這種情況,如果p還保存了一個鎖那么也將不會被釋放,進而導致死鎖 4 p.is_alive():如果p仍然運行,回傳True 5 p.join([timeout]):主執行緒等待p終止(強調:是主執行緒處于等的狀態,而p是處于運行的狀態),timeout是可選的超時時間,需要強調的是,p.join只能join住start開啟的行程,而不能join住run開啟的行程
屬性介紹:
1 p.daemon:默認值為False,如果設為True,代表p為后臺運行的守護行程,當p的父行程終止時,p也隨之終止,并且設定為True后,p不能創建自己的新行程,必須在p.start()之前設定 2 p.name:行程的名稱 3 p.pid:行程的pid 4 p.exitcode:行程在運行時為None、如果為–N,表示被信號N結束(了解即可) 5 p.authkey:行程的身份驗證鍵,默認是由os.urandom()隨機生成的32字符的字串,這個鍵的用途是為涉及網路連接的底層行程間通信提供安全性,這類連接只有在具有相同的身份驗證鍵時才能成功(了解即可)
注意:在windows中Process()必須放到# if __name__ == '__main__':下
在windows系統中應該把全域變數定義在if __name__ == '__main__'之上就可以了
# 開啟行程的方式一: import time import os from multiprocessing import Process def task(n, tag): print("%s is running" % tag) time.sleep(3) print("%s is done" % tag) if __name__ == '__main__': p1 = Process(target=task, args=(5, "子行程1")) p2 = Process(target=task, args=(3, "子行程2")) p3 = Process(target=task, args=(2, "子行程3")) p1.start() p2.start() p3.start() print("主:%s,,," % os.getpid())
ps:得用start啟動行程,不能用run,這里底層Process會做很多事情
# 開啟行程的方式二: import time import os from multiprocessing import Process class Myprocess(Process): def __init__(self,tag): super().__init__() self.tag = tag def run(self) -> None: print("%s is running" % self.tag) time.sleep(3) print("%s is done" % self.tag) if __name__ == '__main__': p1 = Myprocess("行程1") p2 = Myprocess("行程2") p3 = Myprocess("行程3") p1.start() # p1.run() p2.start() # p2.run() p3.start() # p3.run() print("主:%s,,," % os.getpid())
二、Process物件的join方法
join:主行程等,等待子行程結束
#例1
import time import os from multiprocessing import Process def task(n, tag): print("%s is running" % tag) time.sleep(n) print("%s is done" % tag) if __name__ == '__main__': p1 = Process(target=task, args=(3, "子行程1")) p2 = Process(target=task, args=(4, "子行程2")) p3 = Process(target=task, args=(5, "子行程3")) # start=time.time()
#不一定先啟動p1但先啟動誰取決于作業系統,先提交不一定誰先啟動可能p2 可能p3 p1.start() p2.start() p3.start() p1.join() p3.join() p2.join()#.join順序不同,結果?
#如果有p.join(0.0001) #意思是等待p停止,等0.0001秒就不再等了
#很明顯p.join()是讓主執行緒等待p的結束,卡住的是主執行緒而絕非行程p
#詳細決議如下:
#行程只要start就會在開始運行了,所以p1-p4.start()時,系統中已經有四個并發的行程了
#而我們p1.join()是在等p1結束,沒錯p1只要不結束主執行緒就會一直卡在原地,這也是問題的關鍵
#join是讓主執行緒等,而p1-p3仍然是并發執行的,p1.join的時候,其余p2,p3仍然在運行,等#p1.join結束,可能p2,p3早已經結束了,這樣p2.join,p3.join.p4.join直接通過檢測,無需等待
# 所以3個join花費的總時間仍然是耗費時間最長的那個行程運行的時間
print(p1.pid) print(p2.pid) print(p3.pid) # print(time.time() - start) print("主:%s,,," % os.getpid())
#例2 import time import os from multiprocessing import Process def task(n, tag): print("%s is running" % tag) time.sleep(n) print("%s is done" % tag) if __name__ == '__main__': p1 = Process(target=task, args=(3, "子行程1")) p2 = Process(target=task, args=(4, "子行程2")) p3 = Process(target=task, args=(5, "子行程3")) # start=time.time() p1.start() p1.join() p2.start() p2.join() p3.start() p3.join() print(p1.pid) print(p2.pid) print(p3.pid) # print(time.time() - start) print("主:%s,,," % os.getpid())
---36---
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/40967.html
標籤:Python
