打開壹個子流程
Process類是在多重處理中提供的,用於生成流程實例。
Process([group [,target [,name [,args [,kwargs]]]])1
分組分組,實際上並沒有用到。
Target表示調用對象,可以傳入方法名。
Args的意思是以元組的形式給調用對象提供參數。例如,target是函數A,它有兩個參數m,n,所以參數是args=(m,n)。
Kwargs表示調用對象的字典。
Name是別名,相當於給這個進程起了壹個名字。
先說壹個小例子:
# -*-編碼:utf-8-*-來自多處理導入進程,pool import OS import time def run _ proc(wTime):
n = 0
而n & lt3: print "子進程% s run," % os.getpid()," {0} "format (time.ctime ()) #獲取當前進程號和運行時間。
Time.sleep(wTime) # Wait (sleep)
n+= 1 if _ _ name _ _ = = " _ _ main _ _ ":
p = Process(target=run_proc,args=(2,)?#申請子流程
運行流程
打印“父流程運行”。子進程是“p.pid print”父進程end,{0}。format(time . ctime())1234567891011213141516171819
運行結果:
父流程運行。子流程是30196?
父流程結束,Mon Mar 27 11:20:21 2017?
子流程30196運行,Mon Mar 27 11:20:21 2017?
子流程30196運行,Mon Mar 27 11:20:23 2017?
子流程30196運行,周壹至3月27日11:20:25 2017
從運行結果來看,父進程運行後子進程還在運行,可能會造成僵屍進程。
通常,當子進程終止時,它會通知父進程,清除它所占用的內存,並在內核中留下自己的退出信息。當父進程知道子進程結束時,它會從內核中取出子進程的退出信息。但是,如果父進程在子進程之前終止,這可能會導致子進程的退出信息留在內核中,子進程就會變成僵屍進程。當僵屍進程大量積累時,內存空間就會被擠壓。
有什麽辦法可以避免僵屍進程??
本文介紹了進程的壹個屬性deamon。當其值為TRUE時,其父進程結束,該進程也直接終止運行(即使尚未結束運行)。?
所以在上面的程序中加上p.deamon = true,看看效果。
# -*-編碼:utf-8-*-來自多處理導入進程,pool import OS import time def run _ proc(wTime):
n = 0
而n & lt3: print "子進程%s run," % os.getpid()," {0} "格式(time.ctime())
睡眠時間(wTime)
n+= 1 if _ _ name _ _ = = " _ _ main _ _ ":
p =進程(target=run_proc,args=(2,))
P.daemon = True #加入守護進程
p.start() print "父進程運行。子進程是“p.pid print”父進程end,{0}。format(time . ctime())123456789101121314151617181920
實施結果:
父流程運行。子流程是31856?
父流程結束,周壹至三月27日11:40:10 2017
又是這個問題,子流程沒有完成,這不是預期的結果。子進程執行後,有沒有辦法結束父進程??
這裏引入P.join()方法,使得父進程只有在子進程執行完畢後才執行下面的代碼。
# -*-編碼:utf-8-*-來自多處理導入進程,pool import OS import time def run _ proc(wTime):
n = 0
而n & lt3: print "子進程%s run," % os.getpid()," {0} "格式(time.ctime())
睡眠時間(wTime)
n+= 1 if _ _ name _ _ = = " _ _ main _ _ ":
p =進程(target=run_proc,args=(2,))
p.daemon = True
開始()
P.join() #添加聯接方法
打印“父流程運行”。子進程是“p.pid print”父進程end,{0}。format(time . ctime())12345678910112131415161718192021
實施結果:
子流程32076運行,Mon Mar 27 11:46:07 2017?
子流程32076運行,3月27日星期壹11:46:09 2017?
子流程32076運行,3月27日星期壹11:46:11 2017?
父流程運行。子流程是32076?
父流程結束,周壹至三月27日11:46:13 2017
這樣所有的過程都可以順利進行。
將流程定義為類
通過繼承process類,可以自定義Process類,實現run方法。實例p通過調用p.start()自動調用run方法。?
如下所示:
# -*-編碼:utf-8-*-來自多處理導入進程,pool import OS import time class my Process(Process):
def __init__(self,wTime):
過程。__init__(self)
self.wTime = wTime def run(self):
n = 0
而n & lt3: print "子進程%s run," % os.getpid()," {0} "格式(time.ctime())
time.sleep(self.wTime)
n+= 1 if _ _ name _ _ = = " _ _ main _ _ ":
p = Myprocess(2)
p.daemon = True
P.start() #自動調用run方法。
p.join() print "父進程運行。子進程是“p.pid print”父進程end,{0}。format(time . ctime())1234567891011213141516171819202122232428
執行結果與前面的示例相同。
創建多個流程
在很多情況下,系統需要創建多個進程來提高CPU的利用率。當數量較少時,可以手工生成壹個流程實例。當進程數量較大時,可能會使用循環,但這需要程序員手動管理系統中並發進程的數量,有時非常麻煩。這時候進程池池就可以發揮作用了。您可以通過傳遞參數來限制並發進程的數量。默認值是CPU核心的數量。?
直接上例:
#-*-編碼:utf-8-*-from多處理導入進程,pool導入OS,timedef run _ proc (name): # #為進程調用定義壹個函數。
對於範圍(5)中的I:
Time.sleep(0.2) #睡眠0.2秒。
Print' run子進程% s(% s)%(name,os.getpid ()) #如果_ _ name _ =' _ _ main _': #執行主進程,則執行此函數壹次需要1秒。
“運行主進程(%s)。”% (os.getpid())
MainStart = time.time() #記錄主進程開始的時間。
p =池(8)?#打開進程池
對於範圍內的I(16):#打開14進程。
P.apply _ async (run_proc,args = ('process'+str (i),)#每個進程都調用run_proc函數。
#args表示傳遞給函數的參數。
打印“正在等待所有子流程完成...”
P.close() #關閉進程池。
p.join()?#在主進程繼續執行之前,等待所有打開的進程被執行。
打印“所有子流程完成”
mainEnd = time.time()?#記錄主流程的結束時間
打印'所有進程運行了%0.2f秒'% (mainEnd-mainStart)?#主進程執行時間123456789101213141516161665438。
實施結果:?
開始部分
運行主流程(30920)。?
正在等待所有子流程完成…?
運行子進程Process0 (32396)?
運行子進程Process3 (25392)?
運行子進程Process1 (28732)?
運行子進程Process2 (32436)
最後壹部分:
運行子進程Process15 (25880)?
所有子流程都完成了嗎?
所有過程持續2.49秒。
相關說明:
這裏,並發進程的數量被進程池限制為8個,當程序運行時,將生成16個進程。進程池將自動管理系統中的並發進程數,其余的將在隊列中等待。並發進程的數量是有限的,因為系統中並發進程越多越好。過多的並發進程可能會使CPU將大部分時間花在進程調度上,而不是執行有效的計算。
當采用多進程並發技術時,就單個處理器而言,其進程的執行是串行的。而在某個時刻(比如執行結果的開始,每個進程的執行順序是不確定的),哪個進程獲得CPU資源並執行是不可預測的,這就體現了進程的異步性。
如果單個程序執行run_proc函數14次,至少需要16秒。通過進程的並發,只需要2.49秒,可見並發的優勢。