1. 程式人生 > 程式設計 >python 程序池pool使用詳解

python 程序池pool使用詳解

和選用執行緒池來關係多執行緒類似,當程式中設定到多程序程式設計時,Python 提供了更好的管理多個程序的方式,就是使用程序池。

在利用 Python 進行系統管理的時候,特別是同時操作多個檔案目錄,或者遠端控制多臺主機,並行操作可以節約大量的時間。

當被操作物件數目不大時,可以直接利用 multiprocessing 中的 Process 動態生成多個程序,十幾個還好,但如果是上百個,上千個目標,手動的去限制程序數量卻又太過繁瑣,此時可以發揮程序池的功效。

Pool可以提供指定數量的程序供使用者呼叫,當有新的請求提交到 pool 中時,如果程序池還沒有滿,那麼就會建立一個新的程序用來執行該請求;但如果池中的程序數已經達到規定最大值,那麼該請求就會等待,直到池中有程序結束,才會建立新的程序來它。

Python multiprocessing 模組提供了 Pool() 函式,專門用來建立一個程序池,該函式的語法格式如下:

multiprocessing.Pool( processes )

其中,processes 引數用於指定該程序池中包含的程序數。

如果程序是 None,則預設使用 os.cpu_count() 返回的數字(根據本地的 cpu 個數決定,processes 小於等於本地的 cpu 個數)。

請看下面的例項:

from multiprocessing import Pool
import os
import time
import random

def worker(msg):
  t_start = time.time()
  print("%s開始執行,程序號為%d" % (msg,os.getpid()))
  # random.random()隨機生成0~1之間的浮點數
  time.sleep(random.random()*2)
  t_stop = time.time()
  print(msg,"執行完畢,耗時%0.2f" % (t_stop-t_start))

if __name__ == "__main__":
  po = Pool(3) # 定義一個程序池,最大程序數3
  for i in range(0,8):
    # Pool().apply_async(要呼叫的目標,(傳遞給目標的引數元祖,))
    # 每次迴圈將會用空閒出來的子程序去呼叫目標
    po.apply_async(worker,(i,))

  print("----start----")
  # 關閉程序池,關閉後po不再接收新的請求
  po.close()
  # 等待po中所有子程序執行完成,必須放在close語句之後
  po.join()
  print("-----end-----")

執行結果:

python 程序池pool使用詳解

multiprocessing.Pool 常用方法說明

apply_async(func[,args[,kwds]]) :使用非阻塞方式呼叫 func(並行執行,堵塞方式必須等待上一個程序退出才能執行下一個程序),args 為傳遞給 func 的引數列表,kwds 為傳遞給 func 的關鍵字引數列表。

close():關閉 Pool,使其不再接受新的任務。

terminate():不管任務是否完成,立即終止。

join():主程序阻塞,等待子程序的退出, 必須在 close 或 terminate 之後使用。

程序池中的 Queue

如果要使用 Pool 建立程序,就需要使用 multiprocessing.Manager() 中的 Queue(),而不是 multiprocessing.Queue(),否則會得到一條如下的錯誤資訊:

RuntimeError: Queue objects should only be shared between processes through inheritance.

下面的例項演示了程序池中的程序如何通訊:

from multiprocessing import Manager,Pool
import os
import time
import random

def writer(q):
  print("writer啟動(%s),父程序為(%s)" % (os.getpid(),os.getppid()))
  for i in "xiaoming":
    q.put(i)

def reader(q):
  print("reader啟動(%s),os.getppid()))
  for i in range(q.qsize()):
    print("reader從Queue獲取到訊息:%s" % q.get(True))

if __name__ == "__main__":
  print("(%s) start" % os.getpid())
  # 使用Manager中的Queue
  q = Manager().Queue()
  po = Pool()
  po.apply_async(writer,(q,))
  # 先讓上面的任務向Queue存入資料,然後再讓下面的任務開始從中取資料
  time.sleep(1)
  po.apply_async(reader,))
  po.close()
  po.join()
  print("(%s) End" % os.getpid())

執行結果:

(17528) start
writer啟動(2216),父程序為(17528)
reader啟動(2216),父程序為(17528)
reader從Queue獲取到訊息:x
reader從Queue獲取到訊息:i
reader從Queue獲取到訊息:a
reader從Queue獲取到訊息:o
reader從Queue獲取到訊息:m
reader從Queue獲取到訊息:i
reader從Queue獲取到訊息:n
reader從Queue獲取到訊息:g
(17528) End

以上就是python 程序池pool使用詳解的詳細內容,更多關於python 程序池pool的資料請關注我們其它相關文章!