子程序太多,還是要用到程序池 Pool

2021-10-24 18:56:50 字數 3294 閱讀 5781

和選用執行緒池來關係多執行緒類似,當程式中設定到多程序程式設計時,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

defworker

(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):

# 每次迴圈將會用空閒出來的子程序去呼叫目標

(i,)

)print

("----start----"

)# 關閉程序池,關閉後po不再接收新的請求

po.close(

)# 等待po中所有子程序執行完成,必須放在close語句之後

po.join(

)print

("-----end-----"

)

執行結果:

multiprocessing.pool 常用方法說明

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

defwriter

(q):

print

("writer啟動(%s),父程序為(%s)"

%(os.getpid(

), os.getppid())

)for i in

"xiaoming"

: q.put(i)

defreader

(q):

print

("reader啟動(%s),父程序為(%s)"

%(os.getpid(

), 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(

)(q,))

# 先讓上面的任務向queue存入資料,然後再讓下面的任務開始從中取資料

time.sleep(1)

(q,)

) 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

父程序與子程序管道

int main else return 0 先在父程序中建立管道,然後建立子程序,子程序複製了父程序管道檔案的檔案描述符,所以父程序和子程序各具有2個管道描述符,當在子程序中關閉讀端,這時關閉的是子程序中管道檔案的讀端,而父程序的讀端沒有關閉,這時子程序往寫段寫資料的時候,因管道讀端未完全關閉,所...

子程序父程序檔案共享

父子程序全域性變數不共享 寫時複製,讀時共享 檔案父子共享,而且關閉時父子程序都要close fd 我的理解是 雖然fork前的 只執行一次,但是建立子程序時複製使用者空間,此時檔案的狀態一同複製了 驗證父子程序,檔案共享 int main int argc,char ar else if pid ...

子程序清理

一般我們在程式設計的時候,我們使用wait來獲取子程序的退出狀態,但是wait將會阻塞等到子程序結束。對於waitpid來說 pid t waitpid pid t pid,int statloc,int options 我們可以通過設定第3個引數options為wnohang來使waitpid為非...