程式池:   

   在利用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方法,如果不阻塞主程式,會導致主程式往下執行到結束,子程式都還沒有返回結果

   

  程式池呼叫後返回引數

# -*- 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()