系統自帶的fork模塊建立的多進程是基於Linux或Unix平臺的,而window平臺並不支持;html
python中的multiprocess爲跨平臺版本的多進程模塊,支持子進程、通訊和共享數據、執行不一樣形式的同步,提供了Process(進程)、Pool(進程池)、Queue(隊列)、Pipe(管道)、Lock等組件python
建立進程的類:linux
Process([group [, target [, name [, args [, kwargs]]]]]) 編程
group:實質上不使用,線程組,目前尚未實現,庫引用中提示必須是Nonewindows
target:調用對象/目標函數dom
name:給進程賦予一個名字函數
args:調用對象的位置參數元組 / 按位置給目標函數傳參spa
kwargs:調用對象的字典 / 以字典形式向目標函數傳參.net
實例方法 :線程
p爲進程對象的屬性
p.start() 啓動某一個進程
p.join([timeout]) 主進程阻塞等待子進程timeout時間後的退出,在時間內若主進程已執行完成,暫時不會退出,而是等待子進程的退出,而後處理子進程後本身再退出
p.is_alive() 進程的狀態
p.run() 調用run方法,若是實例進程時未制定傳入target,這star執行t默認run()方法。
p.terminate() 無論任務是否完成,當即中止工做進程。
屬性:
p.name 建立的進程的名稱
p.authkey
p.exitcode(進程在運行時爲None、若是爲–N,表示被信號N結束)。
p.pid 建立的子進程PID號
p.daemon 若設置必須置於start調用前進行(和線程的setDeamon功能同樣(將父進程設置爲守護進程,當父進程結束時,子進程也結束);
默認爲false,即主進程執行結束後不退出,等待子進程執行後先退出,而後主進程再退出;
設置爲True時,主進程執行後當即退出,而且該主進程的全部子進程也退出
通常步驟爲
(1)肯定事件,將事件封裝爲函數
(2)調用Process類生成響應的子進程對象
(3)調用start()運行子進程
import multiprocessing as mp def test(): pass p = mp.Process(target=test) # 建立子進程 p.start() # 開始執行子進程 p.join() # 等待子進程結束
注意:
一、Process對象能夠建立進程,但Process對象自己不是進程。
二、主進程執行完畢後會默認等待子進程結束後回收資源,不須要手動回收資源;join()函數來控制父子進程的結束順序,待子進程結束後清理子進程全部信息並回收資源。
三、採用Process對象建立進程後,子進程會將主進程的Process對象徹底複製一份,這樣父子進程各有一個Process對象,p.start()啓動子進程,主進程中的Process對象做爲靜態對象存在,不執行。
四、當子進程執行完畢後,產生的「殭屍進程」會被join()函數回收;或者再有另外一條進程開啓,start()函數也會回收「殭屍進程」,因此不必定須要寫join函數。
五、window系統平臺中的子進程結束後會當即自動清除子進程的Process對象,而linux系統平臺中的子進程Process對象結束後,若是沒有join()函數或start()函數時則會在主進程結束後統一清除。
另外還能夠經過繼承Process對象來重寫run方法建立進程,這裏再也不贅述。
import multiprocessing as mp from time import sleep from random import randint import os def test(): sleep(randint(0,4)) print(os.getppid(),'-------',os.getpid()) print("Testing") for i in range(5): p = mp.Process(target=test) #原test()函數已經不是普通的函數,Process對象已經將其轉變成進程。 p.start()
運行
4710 ------- 4711 Testing 4710 ------- 4715 Testing 4710 ------- 4712 Testing 4710 ------- 4713 Testing 4710 ------- 4714 Testing
說明:從運行結果可知,PID=4710的父進程建立了5個子進程(不一樣的PID對應不一樣的子進程)。
import multiprocessing as mp from time import sleep a = 10 def worker(sec): print(a) sleep(sec) print('worker ......') print(a) p = mp .Process(name = 'child', target = worker,args = (5,)) #元組傳參 #p進程對象的屬性 # p.daemon = True p.start() #啓動進程 print(p.pid) #建立的子進程的PID號 print(p.name) #建立的進程的名稱 print(p.is_alive()) #進程的狀態 a = 100000 p.join() #主進程阻塞等待子進程的退出 print("************main****************") worker(1)
運行
5399 child True 10 worker ...... 10 ************main**************** 100000 worker ...... 100000
注意:
(1)元組傳參args = (5,) 而非args = (5) ,一個元素時需注意。
(2)當建立子進程後,在主進程中從新綁定變量值時,子進程中的變量不會變化。
(3)p.daemon = True / False,
daemon(守護進程)默認是False,即主進程(阻塞)會等待子進程結束;
True則爲直接結束主進程,子進程也隨之結束,當主進程中加入阻塞函數join時,該句失效。
import multiprocessing as mp from time import sleep import os a = 100 def worker(sec,msg): print(a) sleep(sec) print(os.getppid(),'-------',os.getpid()) print(msg) print(a) for i in range(5): p = mp.Process\ (name = 'Child%d'%i,target=worker, # args = (2,"child process"),\ kwargs={'sec':2,'msg':"child process"}) p.start() sleep(1) a = 100000 p.join()
運行
100 100 100 100 100 5590 ------- 5592 child process 100 5590 ------- 5591 child process 100 5590 ------- 5593 child process 100 5590 ------- 5594 child process 100 5590 ------- 5595 child process 100
說明:
(1)這裏面中的字典傳參與元組傳參的能夠相互替代,但元素傳參需注意位置關係
(2)開始時輸出連續打印出100是因爲子進程中sleep()所致,當去掉時,連續執行數次(>3)時100均非連續;同時子進程PID號也是亂序(此也說明子進程相互獨立)。
from multiprocessing import Process #導入Process模塊 import os def test(name): ''' :param : :return: 下段代碼適用於Linux中運行,因windows下os模塊不支持getppid() ''' print("Process ID: %s" % (os.getpid())) print("Parent Process ID: %s" % (os.getppid())) # windows下,建立進程的代碼一下要放在main函數裏面 if __name__ == "__main__": proc = Process(target=test, args=('nmask',)) proc.start() proc.join()
該段代碼沒有在window下嘗試運行,在Linux虛擬機上運行正常;相信但要有所懷疑!
詳細參看
multiprocessing解析(一):Process的解析