python多進程實例詳解


寫在前面:python中的多線程其實並不是真正的多線程,如果想要充分地使用多核CPU的資源,在python中大部分情況需要使用多進程。Python提供了非常好用的多進程包multiprocessing,只需要定義一個函數,Python會完成其他所有事情。借助這個包,可以輕松完成從單進程到並發執行的轉換。

1.multiprocessing模塊提供了一個Process類來代表一個進程對象

import os import time import multiprocessing def run_proc(name): # 子進程要執行的代碼 print '運行子進程 %s ,子進程號為(%s)...' % (name, os.getpid()) print "我的處理內容是:%s+%s=?" % (name,name) return name if __name__=='__main__': start = time.time() print '父進程號為 %s.' % os.getpid() print('----------------------------------------') job = [] for i in range(3): p = multiprocessing.Process(target=run_proc, args=(i,))#多進程 job.append(p) print '子進程%d開啟...'%i p.start() # print '子進程%d結束...'    %i print
#加join()可以讓主線程一直等待全部的子線程結束之后,主線程自身才結束,程序退出
for t in job: t.join()#join()方法可以等待子進程結束后再繼續往下運行,通常用於進程間的同步 end = time.time() print end-start

運行結果如下:

父進程號為 4924.
----------------------------------------
子進程0開啟...
子進程0結束...

子進程1開啟...
子進程1結束...

子進程2開啟...
運行子進程 0 ,子進程號為(5516)...
我的處理內容是:0+0=?
運行子進程 1 ,子進程號為(5517)...
我的處理內容是:1+1=?
運行子進程 2 ,子進程號為(5523)...
我的處理內容是:2+2=?
子進程2結束...

0.0220789909363

如果想要返回多進程process處理得到的結果,只需要利用multiprocessing 中的Manager類即可,稍改代碼:

import os import time from multiprocessing import Manager def run_proc(name,return_list): # 子進程要執行的代碼 print '運行子進程 %s ,子進程號為(%s)...' % (name, os.getpid()) print "我的處理內容是:%s+%s=?" % (name,name) return_list.append(name) if __name__=='__main__': print '父進程號為 %s.' % os.getpid() print('----------------------------------------') manager = Manager() return_list = manager.list() #return_dict = manager.dict() 也可以使用字典dict job = [] for i in range(3): p = multiprocessing.Process(target=run_proc, args=(i,return_list))#多進程 job.append(p) print '子進程%d開啟...'%i p.start() print '子進程%d結束...'    %i print for t in job: t.join() print "所有子進程處理得到的結果都在return_list中,值為:",return_list

運行結果如下:

父進程號為 4924.
----------------------------------------
子進程0開啟...
子進程0結束...

子進程1開啟...
子進程1結束...

子進程2開啟...
運行子進程 0 ,子進程號為(5614)...
我的處理內容是:0+0=?
運行子進程 1 ,子進程號為(5616)...
我的處理內容是:1+1=?
運行子進程 2 ,子進程號為(5623)...
我的處理內容是:2+2=?
子進程2結束...

所有子進程處理得到的結果都在return_list中,值為: [0, 1, 2]

2.Pool:如果要啟動大量的子進程,可以用進程池的方式批量創建子進程:

from multiprocessing import Pool import os, time, random def long_time_task(name): print '運行任務 %s ,子進程號為(%s)...' % (name, os.getpid()) print "我就是子進程號為(%s)處理的內容" % (os.getpid()) start = time.time() time.sleep(random.random() * 3) end = time.time() print '任務 %s 運行了 %0.2f 秒.' % (name, (end - start)) return name if __name__=='__main__': print '父進程號為 %s.' % os.getpid() rst = [] p = Pool(4) #進程池中含有4個子進程 for i in range(5): #4個子進程完成5個任務,所以有一個任務是需要等某個進程空閑再處理 a = p.apply_async(long_time_task, args=(i,)) #a是進程處理函數long_time_task的返回結果 rst.append(a) #將次得到的結果添加到數組rst中去 print '等待所有子進程結束...' p.close() p.join()#等待所有子進程執行完畢。調用join()之前必須先調用close(),調用close()之后就不能繼續添加新的Process了。 print '所有子進程結束...'

運行結果如下:

父進程號為 3378. 運行任務 0 ,子進程號為(4621)... 運行任務 2 ,子進程號為(4624)... 運行任務 1 ,子進程號為(4622)... 我就是子進程號為(4621)處理的內容 我就是子進程號為(4622)處理的內容 運行任務 3 ,子進程號為(4627)... 我就是子進程號為(4624)處理的內容 我就是子進程號為(4627)處理的內容 任務 1 運行了 0.16 秒. 運行任務 4 ,子進程號為(4622)... 我就是子進程號為(4622)處理的內容 等待所有子進程結束... 任務 2 運行了 0.98 秒. 任務 4 運行了 0.89 秒. 任務 3 運行了 2.25 秒. 任務 0 運行了 2.89 秒. 所有子進程結束...

直接輸出rst不會得到想要的結果:

rst 運行結果: [<multiprocessing.pool.ApplyResult at 0x7ffa6c682c90>, <multiprocessing.pool.ApplyResult at 0x7ffa6c587590>, <multiprocessing.pool.ApplyResult at 0x7ffa6c587610>, <multiprocessing.pool.ApplyResult at 0x7ffa6c5876d0>, <multiprocessing.pool.ApplyResult at 0x7ffa6c587790>]

這是需要用到.get()方法:

rst = [i.get() for i in rst] rst 運行結果: [0, 1, 2, 3, 4]


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM