Python多進(jìn)程multiprocessing.Pool類詳解
multiprocessing模塊
multiprocessing包是Python中的多進(jìn)程管理包。它與 threading.Thread類似,可以利用multiprocessing.Process對(duì)象來(lái)創(chuàng)建一個(gè)進(jìn)程。該進(jìn)程可以允許放在Python程序內(nèi)部編寫的函數(shù)中。該P(yáng)rocess對(duì)象與Thread對(duì)象的用法相同,擁有is_alive()、join([timeout])、run()、start()、terminate()等方法。屬性有:authkey、daemon(要通過(guò)start()設(shè)置)、exitcode(進(jìn)程在運(yùn)行時(shí)為None、如果為–N,表示被信號(hào)N結(jié)束)、name、pid。此外multiprocessing包中也有Lock/Event/Semaphore/Condition類,用來(lái)同步進(jìn)程,其用法也與threading包中的同名類一樣。multiprocessing的很大一部份與threading使用同一套API,只不過(guò)換到了多進(jìn)程的情境。
這個(gè)模塊表示像線程一樣管理進(jìn)程,這個(gè)是multiprocessing的核心,它與threading很相似,對(duì)多核CPU的利用率會(huì)比threading好的多。
看一下Process類的構(gòu)造方法:
__init__(self, group=None, target=None, name=None, args=(), kwargs={})
參數(shù)說(shuō)明:
group:進(jìn)程所屬組?;静挥?
target:表示調(diào)用對(duì)象。
args:表示調(diào)用對(duì)象的位置參數(shù)元組。
name:別名
kwargs:表示調(diào)用對(duì)象的字典。
創(chuàng)建進(jìn)程的簡(jiǎn)單實(shí)例:
#coding=utf-8 import multiprocessing def do(n) : #獲取當(dāng)前線程的名字 name = multiprocessing.current_process().name print name,'starting' print "worker ", n return if __name__ == '__main__' : numList = [] for i in xrange(5) : p = multiprocessing.Process(target=do, args=(i,)) numList.append(p) p.start() p.join() print "Process end."
執(zhí)行結(jié)果:
Process-1 starting worker 0 Process end. Process-2 starting worker 1 Process end. Process-3 starting worker 2 Process end. Process-4 starting worker 3 Process end. Process-5 starting worker 4 Process end.
創(chuàng)建子進(jìn)程時(shí),只需要傳入一個(gè)執(zhí)行函數(shù)和函數(shù)的參數(shù),創(chuàng)建一個(gè)Process實(shí)例,并用其start()方法啟動(dòng),這樣創(chuàng)建進(jìn)程比f(wàn)ork()還要簡(jiǎn)單。
join()方法表示等待子進(jìn)程結(jié)束以后再繼續(xù)往下運(yùn)行,通常用于進(jìn)程間的同步。
注意:
在Windows上要想使用進(jìn)程模塊,就必須把有關(guān)進(jìn)程的代碼寫在當(dāng)前.py文件的if __name__ == ‘__main__' :語(yǔ)句的下面,才能正常使用Windows下的進(jìn)程模塊。Unix/Linux下則不需要。
Pool類
在使用Python進(jìn)行系統(tǒng)管理時(shí),特別是同時(shí)操作多個(gè)文件目錄或者遠(yuǎn)程控制多臺(tái)主機(jī),并行操作可以節(jié)約大量的時(shí)間。如果操作的對(duì)象數(shù)目不大時(shí),還可以直接使用Process類動(dòng)態(tài)的生成多個(gè)進(jìn)程,十幾個(gè)還好,但是如果上百個(gè)甚至更多,那手動(dòng)去限制進(jìn)程數(shù)量就顯得特別的繁瑣,此時(shí)進(jìn)程池就派上用場(chǎng)了。
Pool類可以提供指定數(shù)量的進(jìn)程供用戶調(diào)用,當(dāng)有新的請(qǐng)求提交到Pool中時(shí),如果池還沒(méi)有滿,就會(huì)創(chuàng)建一個(gè)新的進(jìn)程來(lái)執(zhí)行請(qǐng)求。如果池滿,請(qǐng)求就會(huì)告知先等待,直到池中有進(jìn)程結(jié)束,才會(huì)創(chuàng)建新的進(jìn)程來(lái)執(zhí)行這些請(qǐng)求。
下面介紹一下multiprocessing 模塊下的Pool類下的幾個(gè)方法
apply()
函數(shù)原型:
apply(func[, args=()[, kwds={}]])
該函數(shù)用于傳遞不定參數(shù),主進(jìn)程會(huì)被阻塞直到函數(shù)執(zhí)行結(jié)束(不建議使用,并且3.x以后不在出現(xiàn))。
apply_async()
函數(shù)原型:
apply_async(func[, args=()[, kwds={}[, callback=None]]])
與apply用法一樣,但它是非阻塞且支持結(jié)果返回進(jìn)行回調(diào)。
map()
函數(shù)原型:
map(func, iterable[, chunksize=None])
Pool類中的map方法,與內(nèi)置的map函數(shù)用法行為基本一致,它會(huì)使進(jìn)程阻塞直到返回結(jié)果。
注意,雖然第二個(gè)參數(shù)是一個(gè)迭代器,但在實(shí)際使用中,必須在整個(gè)隊(duì)列都就緒后,程序才會(huì)運(yùn)行子進(jìn)程。
close()
關(guān)閉進(jìn)程池(pool),使其不在接受新的任務(wù)。
terminate()
結(jié)束工作進(jìn)程,不在處理未處理的任務(wù)。
join()
主進(jìn)程阻塞等待子進(jìn)程的退出,join方法必須在close或terminate之后使用。
multiprocessing.Pool類的實(shí)例:
import time from multiprocessing import Pool def run(fn): #fn: 函數(shù)參數(shù)是數(shù)據(jù)列表的一個(gè)元素 time.sleep(1) return fn*fn if __name__ == "__main__": testFL = [1,2,3,4,5,6] print 'shunxu:' #順序執(zhí)行(也就是串行執(zhí)行,單進(jìn)程) s = time.time() for fn in testFL: run(fn) e1 = time.time() print "順序執(zhí)行時(shí)間:", int(e1 - s) print 'concurrent:' #創(chuàng)建多個(gè)進(jìn)程,并行執(zhí)行 pool = Pool(5) #創(chuàng)建擁有5個(gè)進(jìn)程數(shù)量的進(jìn)程池 #testFL:要處理的數(shù)據(jù)列表,run:處理testFL列表中數(shù)據(jù)的函數(shù) rl =pool.map(run, testFL) pool.close()#關(guān)閉進(jìn)程池,不再接受新的進(jìn)程 pool.join()#主進(jìn)程阻塞等待子進(jìn)程的退出 e2 = time.time() print "并行執(zhí)行時(shí)間:", int(e2-e1) print rl
執(zhí)行結(jié)果:
shunxu:
順序執(zhí)行時(shí)間: 6
concurrent:
并行執(zhí)行時(shí)間: 2
[1, 4, 9, 16, 25, 36]
上例是一個(gè)創(chuàng)建多個(gè)進(jìn)程并發(fā)處理與順序執(zhí)行處理同一數(shù)據(jù),所用時(shí)間的差別。從結(jié)果可以看出,并發(fā)執(zhí)行的時(shí)間明顯比順序執(zhí)行要快很多,但是進(jìn)程是要耗資源的,所以平時(shí)工作中,進(jìn)程數(shù)也不能開(kāi)太大。
程序中的r1表示全部進(jìn)程執(zhí)行結(jié)束后全局的返回結(jié)果集,run函數(shù)有返回值,所以一個(gè)進(jìn)程對(duì)應(yīng)一個(gè)返回結(jié)果,這個(gè)結(jié)果存在一個(gè)列表中,也就是一個(gè)結(jié)果堆中,實(shí)際上是用了隊(duì)列的原理,等待所有進(jìn)程都執(zhí)行完畢,就返回這個(gè)列表(列表的順序不定)。
對(duì)Pool對(duì)象調(diào)用join()方法會(huì)等待所有子進(jìn)程執(zhí)行完畢,調(diào)用join()之前必須先調(diào)用close(),讓其不再接受新的Process了。
再看一個(gè)實(shí)例:
import time from multiprocessing import Pool def run(fn) : time.sleep(2) print fn if __name__ == "__main__" : startTime = time.time() testFL = [1,2,3,4,5] pool = Pool(10)#可以同時(shí)跑10個(gè)進(jìn)程 pool.map(run,testFL) pool.close() pool.join() endTime = time.time() print "time :", endTime - startTime
執(zhí)行結(jié)果:
21 3 4 5 time : 2.51999998093
再次執(zhí)行結(jié)果如下:
1 34 2 5 time : 2.48600006104
結(jié)果中為什么還有空行和沒(méi)有折行的數(shù)據(jù)呢?其實(shí)這跟進(jìn)程調(diào)度有關(guān),當(dāng)有多個(gè)進(jìn)程并行執(zhí)行時(shí),每個(gè)進(jìn)程得到的時(shí)間片時(shí)間不一樣,哪個(gè)進(jìn)程接受哪個(gè)請(qǐng)求以及執(zhí)行完成時(shí)間都是不定的,所以會(huì)出現(xiàn)輸出亂序的情況。那為什么又會(huì)有沒(méi)這行和空行的情況呢?因?yàn)橛锌赡茉趫?zhí)行第一個(gè)進(jìn)程時(shí),剛要打印換行符時(shí),切換到另一個(gè)進(jìn)程,這樣就極有可能兩個(gè)數(shù)字打印到同一行,并且再次切換回第一個(gè)進(jìn)程時(shí)會(huì)打印一個(gè)換行符,所以就會(huì)出現(xiàn)空行的情況。
進(jìn)程實(shí)戰(zhàn)實(shí)例
并行處理某個(gè)目錄下文件中的字符個(gè)數(shù)和行數(shù),存入res.txt文件中,
每個(gè)文件一行,格式為:filename:lineNumber,charNumber
import os
import time
from multiprocessing import Pool
def getFile(path) :
#獲取目錄下的文件list
fileList = []
for root, dirs, files in list(os.walk(path)) :
for i in files :
if i.endswith('.txt') or i.endswith('.10w') :
fileList.append(root + "\\" + i)
return fileList
def operFile(filePath) :
#統(tǒng)計(jì)每個(gè)文件中行數(shù)和字符數(shù),并返回
filePath = filePath
fp = open(filePath)
content = fp.readlines()
fp.close()
lines = len(content)
alphaNum = 0
for i in content :
alphaNum += len(i.strip('\n'))
return lines,alphaNum,filePath
def out(list1, writeFilePath) :
#將統(tǒng)計(jì)結(jié)果寫入結(jié)果文件中
fileLines = 0
charNum = 0
fp = open(writeFilePath,'a')
for i in list1 :
fp.write(i[2] + " 行數(shù):"+ str(i[0]) + " 字符數(shù):"+str(i[1]) + "\n")
fileLines += i[0]
charNum += i[1]
fp.close()
print fileLines, charNum
if __name__ == "__main__":
#創(chuàng)建多個(gè)進(jìn)程去統(tǒng)計(jì)目錄中所有文件的行數(shù)和字符數(shù)
startTime = time.time()
filePath = "C:\\wcx\\a"
fileList = getFile(filePath)
pool = Pool(5)
resultList =pool.map(operFile, fileList)
pool.close()
pool.join()
writeFilePath = "c:\\wcx\\res.txt"
print resultList
out(resultList, writeFilePath)
endTime = time.time()
print "used time is ", endTime - startTime
執(zhí)行結(jié)果:

耗時(shí)不到1秒,可見(jiàn)多進(jìn)程并發(fā)執(zhí)行速度是很快的。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- python multiprocessing多進(jìn)程變量共享與加鎖的實(shí)現(xiàn)
- Python Multiprocessing多進(jìn)程 使用tqdm顯示進(jìn)度條的實(shí)現(xiàn)
- Python multiprocessing多進(jìn)程原理與應(yīng)用示例
- Python多進(jìn)程池 multiprocessing Pool用法示例
- Python3多進(jìn)程 multiprocessing 模塊實(shí)例詳解
- Python多進(jìn)程庫(kù)multiprocessing中進(jìn)程池Pool類的使用詳解
- python使用 multiprocessing 多進(jìn)程處理批量數(shù)據(jù)的示例代碼
相關(guān)文章
使用 Python 創(chuàng)建一個(gè)基于規(guī)則的聊天機(jī)器人
這篇文章主要介紹了使用 Python 創(chuàng)建一個(gè)基于規(guī)則的聊天機(jī)器人,使用 Python 創(chuàng)建一個(gè)簡(jiǎn)單的基于規(guī)則的聊天機(jī)器人 聊天機(jī)器人本身是一種機(jī)器或軟件,它通過(guò)文本或句子模仿人類交互。 簡(jiǎn)而言之,可以使用類似于與人類對(duì)話的軟件進(jìn)行聊天。2021-10-10
Python重復(fù)文件批量整理工具的設(shè)計(jì)與實(shí)現(xiàn)
這篇文章主要為大家詳細(xì)介紹了如何通關(guān)Python編寫一個(gè)重復(fù)文件批量整理工具,可以在文件夾內(nèi)對(duì)文件進(jìn)行去重和分類存儲(chǔ),有需要的可以了解下2025-02-02
python中列表的切片與修改知識(shí)點(diǎn)總結(jié)
在本篇文章里小編給大家分享了關(guān)于python中列表的切片與修改的相關(guān)知識(shí)點(diǎn)內(nèi)容,需要的朋友們學(xué)習(xí)下。2019-07-07
Python寫了個(gè)疫情信息快速查看工具實(shí)例代碼
本次使用PyQt5開(kāi)發(fā)了一款疫情信息快速查看工具,實(shí)現(xiàn)了多個(gè)數(shù)據(jù)源的查看,代碼量不大,功能相當(dāng)于瀏覽器,只是限定了一些特定網(wǎng)址,這篇文章主要介紹了Python寫了個(gè)疫情信息快速查看工具,需要的朋友可以參考下2022-11-11
python3用PIL把圖片轉(zhuǎn)換為RGB圖片的實(shí)例
今天小編就為大家分享一篇python3用PIL把圖片轉(zhuǎn)換為RGB圖片的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-07-07
python實(shí)現(xiàn)12306登錄并保存cookie的方法示例
這篇文章主要介紹了 python實(shí)現(xiàn)12306登錄并保存cookie的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12
pandas or sql計(jì)算前后兩行數(shù)據(jù)間的增值方法
下面小編就為大家分享一篇pandas or sql計(jì)算前后兩行數(shù)據(jù)間的增值方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-04-04

