python學習筆記——multiprocess 多進程組件Pool

來源:互聯網
上載者:User

標籤:產生   學習筆記   文法   roc   iterable   att   bsp   error:   上下   

1 進程池Pool基本概述

在使用Python進行系統管理時,特別是同時操作多個檔案目錄或者遠端控制多台主機,並行操作可以節約大量時間,如果操作的對象數目不大時,還可以直接適用Process類動態產生多個進程,幾十個尚可,若上百個甚至更多時,手動限制進程數量就顯得特別繁瑣,此時進程池就顯得尤為重要。

進程池Pool類可以提供指定數量的進程供使用者調用,當有新的請求提交至Pool中時,若進程池尚未滿,就會建立一個新的進程來執行請求;若進程池中的進程數已經達到規定的最大數量,則該請求就會等待,直到進程池中有進程結束,才會建立新的進程來處理該請求。

2 進程池Pool的文法

 Pool([processes[, initializer[, initargs[, maxtasksperchild[, context]]]]]) 

processes:使用的背景工作處理序的數量;若processes是None,預設適用os.cpu_count()返回的數量。

initializer:若initializer是None,則每一個背景工作處理序在開始的時候就會調用initializer(*initargs)。

maxtasksperchild:背景工作處理序退出前可以完成的任務數,完成後用一個新的背景工作處理序來替代原進程,讓閑置的資源釋放,maxtasksperchild預設是None,此意味只要Pool存在背景工作處理序就一直存活

context: 用在制定背景工作處理序啟動時的上下文,一般使用multiprocessing.Pool()或者一個context對象的Pool()方法來建立一個池,兩種方法都適當的設定了context。

 

執行個體方法:

p為進程池對象

p.apply():

 apply(func[, args=()[, kwds={}]]) 

該函數用於傳遞不定參數,主進程會被阻塞直到函數執行結束,實際上這也就說所謂的同步執行。

同步執行,按照加入進程池的順序執行事件,每次執行完一個再執行另一個,無法擷取傳回值

p.apply_async()

 apply_async(func[, args=()[, kwds={}[, callback=None]]]) 

與apply用法一樣,但它是非阻塞且支援結果返回進行回調;實際上也就是非同步執行。

非同步執行,同時啟動進程池中多個進程執行事件,可以擷取事件傳回值 — <multiprocessing.pool.ApplyResult object at 0x7f7f6e4357f0>

p.map()

 map(func, iterable[, chunksize=None]) 

Pool類中的map方法,與內建map函數用法基本一致,它融合了map函數和apply_async()函數的功能;它會使進程阻塞直到返回結果。

注意:雖然第二個參數是一個迭代器,但實際應用中,必須在整個隊列就緒後,程式才會運行子進程。

p.close():關閉進程池,阻止更多的任務提交到進程池Pool,待任務完成後,背景工作處理序會退出

p.terminate():結束背景工作處理序,不再處理未完成的任務

p.join():等待背景工作執行緒的退出,必須在close()或terminate()之後使用,因被終止的進程需要被父進程調用wait(join等價於wait),否則進程會成為殭屍進程。

 

注意:

(1)使用Pool建立進程池對象,同時進程池中進程已經啟動

(2)向進程池對象中添加事件,事件排隊執行

(3)如果主進程退出,則進程池中所有進程都退出

3 執行個體3.1 基礎執行個體
import multiprocessing as mpdef test():    passp = mp.Pool(processes = 5) # 建立5條進程for i in range(10):    p.apply_async(test) # 向進程池新增工作p.close() # 關閉進程池,不再接受請求p.join() # 等待所有的子進程結束

說明:

(1)進程池Pool被建立出來後, p.apply_async(test) 語句不停地迴圈執行,相當於向進程池中提交了10個請求,它們會被放到一個隊列中。

(2) p = mp.Pool(5) 執行完畢後建立了5條進程,但尚未給它們分配各自的任務;也就意味著,無論有多少任務,實際的進程數只有5條,每次最多5條進程並行。

(3)當Pool中有進程任務執行完畢後,這條進程資源會被釋放,Pool會按先進先出的原則取出一個新的請求給閒置進程繼續執行。

(4)當Pool所有的進程任務完成後,會產生5個殭屍進程,如果主進程/主線程不結束,系統不會自動回收資源,需要調用join函數負責回收。

(5)在建立Pool進程池時,若不指定進程的最大數量,預設建立的進程數為系統的核心數量

(6)如果採用p.apply(test)阻塞方式新增工作,其每次只能向進程池中添加一條任務,然後for迴圈會被阻塞等待,直到添加的任務被執行完畢,進程池中的5個進程交替執行新來的任務,此時相當於單進程。——該語句需要再深刻理解,尚未完全明白

參考:python的multiprocessing模組進程建立、資源回收-Process,Pool

3.2 apply方式新增工作
import  multiprocessing as mpimport osfrom time import sleepdef worker(msg):    print(os.getpid())    sleep(2)    print(msg)    return msg#建立進程池對象p = mp.Pool(processes = 4)#建立4條進程pool_result = []for i in range(10):    msg = ‘hello-%d‘%i    r = p.apply(worker,(msg,))#向進程池中添加事件    pool_result.append(r)#擷取事件函數的傳回值for r in pool_result:    print(‘return:‘,r) p.close()# 關閉進程池,不再接受請求p.join() # 等待進程池中的事件執行完畢,回收進程池

運行

8419hello-08418hello-18420hello-28421hello-38419hello-48418hello-58420hello-68421hello-78419hello-88418hello-9return: hello-0return: hello-1return: hello-2return: hello-3return: hello-4return: hello-5return: hello-6return: hello-7return: hello-8return: hello-9

這段代碼運行較慢,和進程阻塞有關。相當於單線程!

當將代碼(22行)中的 print(‘return:‘,r)  修改為 print(‘return:‘,r.get())  時

8670hello-08671hello-18672hello-28673hello-38670hello-48671hello-58672hello-68673hello-78670hello-88671hello-9Traceback (most recent call last):  File "test1.py", line 22, in <module>    print(‘return:‘,r.get())AttributeError: ‘str‘ object has no attribute ‘get‘

最後報錯: AttributeError: ‘str‘ object has no attribute ‘get‘ 

3.3 applay_async方式新增工作
import multiprocessing as mpimport os from time import sleep def worker(msg):    print(os.getpid())    sleep(2)    print(msg)    return msg#建立進程池對象p = mp.Pool(processes = 4) #建立4條進程pool_result = []for i in range(10):    msg = ‘hello-%d‘%i    r = p.apply_async(worker,(msg,)) #向進程池中添加事件    pool_result.append(r)#擷取事件函數的傳回值for r in pool_result:    print(‘return:‘,r)p.close()#關閉進程池,不再接受請求p.join()# 等待進程池中的事件執行完畢,回收進程池

運行

return: <multiprocessing.pool.ApplyResult object at 0x7f66d0e37d68>return: <multiprocessing.pool.ApplyResult object at 0x7f66d0e37e80>return: <multiprocessing.pool.ApplyResult object at 0x7f66d0e37f98>return: <multiprocessing.pool.ApplyResult object at 0x7f66d0e410f0>return: <multiprocessing.pool.ApplyResult object at 0x7f66d0e41208>return: <multiprocessing.pool.ApplyResult object at 0x7f66d0e41320>return: <multiprocessing.pool.ApplyResult object at 0x7f66d0e41438>return: <multiprocessing.pool.ApplyResult object at 0x7f66d0e41550>return: <multiprocessing.pool.ApplyResult object at 0x7f66d0e41668>return: <multiprocessing.pool.ApplyResult object at 0x7f66d0e41780>8739874087428741hello-0hello-38742hello-187398740hello-28741hello-58739hello-68740hello-7hello-4hello-8hello-9

注意:

(1)由於這個是非同步方式新增工作,所以運行非常快

(2)由於for是內建迴圈函數,執行效率較高,所以在結果的前10行均為for語句執行結果

(3) r = p.apply_async(worker,(msg,)) 執行結果為進度對象。

(4)由於任務是非同步執行,所以在結果中是“亂序”;並不像applay那樣有序列印。

 

同樣將代碼(22行)中的 print(‘return:‘,r) 修改為 print(‘return:‘,r.get())  時,

運行結果

8839884088418842hello-0hello-1hello-38839hello-2884288418840return: hello-0return: hello-1return: hello-2return: hello-3hello-4hello-58839hello-68842hello-7return: hello-4return: hello-5return: hello-6return: hello-7hello-9hello-8return: hello-8return: hello-9

 

python學習筆記——multiprocess 多進程組件Pool

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.