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