程式池:
在利用Python進行系統管理的時候,特別是同時操作多個檔案目錄,或者遠端控制多臺主機,並行操作可以節約大量的時間。當被操作物件數目不大時,可以直接利用multiprocessing中的Process動態成生多個程式,十幾個還好,但如果是上百個,上千個目標,手動的去限制程式數量卻又太過繁瑣,此時可以發揮程式池的功效。
Pool可以提供指定數量的程式供使用者呼叫,當有新的請求提交到pool中時,如果池還沒有滿,那麼就會建立一個新的程式用來執行該請求;但如果池中的程式數已經達到規定最大值,那麼該請求就會等待,直到池中有程式結束,才會建立新的程式來它。
如何使用程式池?
1 如何使用程式池執行函式?
a 不返回引數
# -*- coding: UTF-8 -*- from multiprocessing import Process,Manager,Lock,Pool #要在呼叫程式池執行的函式 def sayHi(num): print "def print result:",num #程式池最大執行數 p = Pool(processes=4) #模擬併發呼叫執行緒池 for i in range(10): p.apply_async(sayHi,[i]) 執行結果: # python demo.py def print result: 0 def print result: 1 def print result: 2 def print result: 3 def print result: 4 def print result: 5
-
apply_async(func[, args[, kwds[, callback]]]) 它是非阻塞,apply(func[, args[, kwds]])是阻塞的(理解區別,看例1例2結果區別)
2 程式池使用之坑~~
# -*- coding: UTF-8 -*- from multiprocessing import Process,Manager,Lock,Pool #要在呼叫程式池執行的函式 def sayHi(num): print "def print result:",num #程式池最大執行數 p = Pool(processes=4) #模擬併發呼叫執行緒池 for i in range(10): p.apply_async(sayHi,[i])
執行結果:
[root@python thread]# python pool.py def print result: 0 def print result: 1 def print result: 2 def print result: 3 def print result: 4 def print result: 5 [root@python thread]# python pool.py def print result: 0 def print result: 1 def print result: 2 def print result: 3 def print result: 4 def print result: 5 def print result: 6 [root@python thread]# python pool.py [root@python thread]# python pool.py [root@python thread]# python pool.py
從上面的例子可以看出,我們連續執行pool.py指令碼,後面的指令碼卻沒有輸出應有的結果,為什麼?
首先對上列程式進行細微調整:
# -*- coding: UTF-8 -*- from multiprocessing import Process,Manager,Lock,Pool def sayHi(num): print "def print result:",num p = Pool(processes=4) for i in range(10): p.apply_async(sayHi,[i]) p.close() p.join() #呼叫join之前,先呼叫close函式,否則會出錯。執行完close後不會有新的程式加入到pool,join函式等待所有子程式結束
返回結果:
[root@python thread]# python pool.py def print result: 0 def print result: 1 def print result: 2 def print result: 3 def print result: 4 def print result: 5 def print result: 6 def print result: 9 def print result: 8 def print result: 7 [root@python thread]# python pool.py def print result: 0 def print result: 1 def print result: 2 def print result: 4 def print result: 3 def print result: 5 def print result: 6 def print result: 7 def print result: 8 def print result: 9 [root@python thread]# python pool.py def print result: 0 def print result: 1 def print result: 2 def print result: 3 def print result: 4 def print result: 5 def print result: 7 def print result: 8 def print result: 9
這次執行完全沒有問題,那麼為何加入close()和join()方法後就會執行正確呢?
-
close() 關閉pool,使其不在接受新的任務。
-
terminate() 結束工作程式,不在處理未完成的任務。
-
join() 主程式阻塞,等待子程式的退出, join方法要在close或terminate之後使用。
原來重點是join方法,如果不阻塞主程式,會導致主程式往下執行到結束,子程式都還沒有返回結果
3 程式池呼叫後返回引數
# -*- coding: UTF-8 -*- from multiprocessing import Process,Manager,Lock,Pool def sayHi(num): return num*num p = Pool(processes=4) #申明一個列表,用來存放各程式返回的結果 result_list =[] for i in range(10): result_list.append(p.apply_async(sayHi,[i])) #將返回結果append到列表中 #迴圈讀出列表返回的結果 for res in result_list: print "the result:",res.get()
注:get()函式得出每個返回結果的值
執行結果:
[root@python thread]# python pool.py the result: 0 the result: 1 the result: 4 the result: 9 the result: 16 the result: 25 the result: 36 the result: 49 the result: 64 the result: 81 [root@python thread]# python pool.py the result: 0 the result: 1 the result: 4 the result: 9 the result: 16 the result: 25 the result: 36 the result: 49 the result: 64 the result: 81 [root@python thread]# python pool.py the result: 0 the result: 1 the result: 4 the result: 9 the result: 16 the result: 25 the result: 36 the result: 49 the result: 64
將結果通過return返回後,寫入列表後,然後再迴圈讀出,你會發現及時不需要join方法,指令碼仍然能正常顯示。
但是為了程式碼更加穩定,還是建議增加主程式阻塞(除非主程式需要等待子程式返回結果):
# -*- coding: UTF-8 -*- from multiprocessing import Process,Manager,Lock,Pool def sayHi(num): return num*num p = Pool(processes=4) #申明一個列表,用來存放各程式返回的結果 result_list =[] for i in range(10): result_list.append(p.apply_async(sayHi,[i])) #將返回結果append到列表中 p.close() p.join() #呼叫join之前,先呼叫close函式,否則會出錯。執行完close後不會有新的程式加入到pool,join函式等待所有子程式結束 #迴圈讀出列表返回的結果 for res in result_list: print "the result:",res.get()