python 进程池
Pool類
在使用Python進行系統管理時,特別是同時操作多個文件目錄或者遠程控制多臺主機,并行操作可以節約大量的時間。如果操作的對象數目不大時,還可以直接使用Process類動態的生成多個進程,十幾個還好,但是如果上百個甚至更多,那手動去限制進程數量就顯得特別的繁瑣,此時進程池就派上用場了。?
Pool類可以提供指定數量的進程供用戶調用,當有新的請求提交到Pool中時,如果池還沒有滿,就會創建一個新的進程來執行請求。如果池滿,請求就會告知先等待,直到池中有進程結束,才會創建新的進程來執行這些請求。
下面介紹一下multiprocessing 模塊下的Pool類下的幾個方法
?
apply()
函數原型:
apply(func[, args=()[, kwds={}]])該函數用于傳遞不定參數,主進程會被阻塞直到函數執行結束(不建議使用,并且3.x以后不在出現)。
?
apply_async()
函數原型:
apply_async(func[, args=()[, kwds={}[, callback=None]]])與apply用法一樣,但它是非阻塞且支持結果返回進行回調。
map()
函數原型:
map(func, iterable[, chunksize=None])Pool類中的map方法,與內置的map函數用法行為基本一致,它會使進程阻塞直到返回結果。?
注意,雖然第二個參數是一個迭代器,但在實際使用中,必須在整個隊列都就緒后,程序才會運行子進程。
close()
關閉進程池(pool),使其不在接受新的任務。
terminate()
結束工作進程,不在處理未處理的任務。
join()
主進程阻塞等待子進程的退出,join方法必須在close或terminate之后使用。
multiprocessing.Pool類的實例:
import time from multiprocessing import Pool def run(fn):#fn: 函數參數是數據列表的一個元素time.sleep(1)return fn*fnif __name__ == "__main__":testFL = [1,2,3,4,5,6] print 'shunxu:' #順序執行(也就是串行執行,單進程)s = time.time()for fn in testFL:run(fn)e1 = time.time()print "順序執行時間:", int(e1 - s)print 'concurrent:' #創建多個進程,并行執行pool = Pool(5) #創建擁有5個進程數量的進程池#testFL:要處理的數據列表,run:處理testFL列表中數據的函數rl =pool.map(run, testFL) pool.close()#關閉進程池,不再接受新的進程pool.join()#主進程阻塞等待子進程的退出e2 = time.time()print "并行執行時間:", int(e2-e1)print rl執行結果:
shunxu: 順序執行時間: 6 concurrent: 并行執行時間: 2 [1, 4, 9, 16, 25, 36]上例是一個創建多個進程并發處理與順序執行處理同一數據,所用時間的差別。從結果可以看出,并發執行的時間明顯比順序執行要快很多,但是進程是要耗資源的,所以平時工作中,進程數也不能開太大。?
程序中的r1表示全部進程執行結束后全局的返回結果集,run函數有返回值,所以一個進程對應一個返回結果,這個結果存在一個列表中,也就是一個結果堆中,實際上是用了隊列的原理,等待所有進程都執行完畢,就返回這個列表(列表的順序不定)。?
對Pool對象調用join()方法會等待所有子進程執行完畢,調用join()之前必須先調用close(),讓其不再接受新的Process了。
再看一個實例:
import time from multiprocessing import Pool def run(fn) :time.sleep(2)print fn if __name__ == "__main__" :startTime = time.time()testFL = [1,2,3,4,5]pool = Pool(10)#可以同時跑10個進程pool.map(run,testFL)pool.close()pool.join() endTime = time.time()print "time :", endTime - startTime執行結果:
213 4 5 time : 2.51999998093再次執行結果如下:
1 342 5 time : 2.48600006104結果中為什么還有空行和沒有折行的數據呢?其實這跟進程調度有關,當有多個進程并行執行時,每個進程得到的時間片時間不一樣,哪個進程接受哪個請求以及執行完成時間都是不定的,所以會出現輸出亂序的情況。那為什么又會有沒這行和空行的情況呢?因為有可能在執行第一個進程時,剛要打印換行符時,切換到另一個進程,這樣就極有可能兩個數字打印到同一行,并且再次切換回第一個進程時會打印一個換行符,所以就會出現空行的情況。
?在利用Python進行系統管理的時候,特別是同時操作多個文件目錄,或者遠程控制多臺主機,并行操作可以節約大量的時間。當被操作對象數目不大時,可以直接利用multiprocessing中的Process動態成生多個進程,10幾個還好,但如果是上百個,上千個目標,手動的去限制進程數量卻又太過繁瑣,這時候進程池Pool發揮作用的時候就到了。
??????Pool可以提供指定數量的進程,供用戶調用,當有新的請求提交到pool中時,如果池還沒有滿,那么就會創建一個新的進程用來執行該請求;但如果池中的進程數已經達到規定最大值,那么該請求就會等待,直到池中有進程結束,才會創建新的進程來它。這里有一個簡單的例子:
? ? ? ? 先創建容量為3的進程池,然后將f(i)依次傳遞給它,運行腳本后利用ps aux | grep pool.py查看進程情況,會發現最多只會有三個進程執行。pool.apply_async()用來向進程池提交目標請求,pool.join()是用來等待進程池中的worker進程執行完畢,防止主進程在worker進程結束前結束。但必pool.join()必須使用在pool.close()或者pool.terminate()之后。其中close()跟terminate()的區別在于close()會等待池中的worker進程執行結束再關閉pool,而terminate()則是直接關閉。result.successful()表示整個調用執行的狀態,如果還有worker沒有執行完,則會拋出AssertionError異常。
? ? ? 利用multiprocessing下的Pool可以很方便的同時自動處理幾百或者上千個并行操作,腳本的復雜性也大大降低。?
?
?
總結
以上是生活随笔為你收集整理的python 进程池的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android Studio 在res中
- 下一篇: 查找算法:插值查找算法实现及分析