Python 多進程并發(fā)操作中進程池Pool的實例
在利用Python進行系統(tǒng)管理的時候,特別是同時操作多個文件目錄,或者遠程控制多臺主機,并行操作可以節(jié)約大量的時間。當被操作對象數(shù)目不大時,可以直接利用multiprocessing中的Process動態(tài)成生多個進程,10幾個還好,但如果是上百個,上千個目標,手動的去限制進程數(shù)量卻又太過繁瑣,這時候進程池Pool發(fā)揮作用的時候就到了。
Pool可以提供指定數(shù)量的進程,供用戶調(diào)用,當有新的請求提交到pool中時,如果池還沒有滿,那么就會創(chuàng)建一個新的進程用來執(zhí)行該請求;但如果池中的進程數(shù)已經(jīng)達到規(guī)定最大值,那么該請求就會等待,直到池中有進程結(jié)束,才會創(chuàng)建新的進程來它。這里有一個簡單的例子:
#!/usr/bin/env python
#coding=utf-8
"""
Author: Squall
Last modified: 2011-10-18 16:50
Filename: pool.py
Description: a simple sample for pool class
"""
from multiprocessing import Pool
from time import sleep
def f(x):
for i in range(10):
print '%s --- %s ' % (i, x)
sleep(1)
def main():
pool = Pool(processes=3) # set the processes max number 3
for i in range(11,20):
result = pool.apply_async(f, (i,))
pool.close()
pool.join()
if result.successful():
print 'successful'
if __name__ == "__main__":
main()
先創(chuàng)建容量為3的進程池,然后將f(i)依次傳遞給它,運行腳本后利用ps aux | grep pool.py查看進程情況,會發(fā)現(xiàn)最多只會有三個進程執(zhí)行。pool.apply_async()用來向進程池提交目標請求,pool.join()是用來等待進程池中的worker進程執(zhí)行完畢,防止主進程在worker進程結(jié)束前結(jié)束。但必pool.join()必須使用在pool.close()或者pool.terminate()之后。其中close()跟terminate()的區(qū)別在于close()會等待池中的worker進程執(zhí)行結(jié)束再關(guān)閉pool,而terminate()則是直接關(guān)閉。result.successful()表示整個調(diào)用執(zhí)行的狀態(tài),如果還有worker沒有執(zhí)行完,則會拋出AssertionError異常。
利用multiprocessing下的Pool可以很方便的同時自動處理幾百或者上千個并行操作,腳本的復(fù)雜性也大大降低。
——————————————————————————————————
Python多進程并發(fā)(multiprocessing)
由于Python設(shè)計的限制(我說的是咱們常用的CPython)。最多只能用滿1個CPU核心。
Python提供了非常好用的多進程包multiprocessing,你只需要定義一個函數(shù),Python會替你完成其他所有事情。借助這個包,可以輕松完成從單進程到并發(fā)執(zhí)行的轉(zhuǎn)換。
1、新建單一進程
如果我們新建少量進程,可以如下:
import multiprocessing
import time
def func(msg):
for i in xrange(3):
print msg
time.sleep(1)
if __name__ == "__main__":
p = multiprocessing.Process(target=func, args=("hello", ))</
p.start()
p.join()
print "Sub-process done."
2、使用進程池
是的,你沒有看錯,不是線程池。它可以讓你跑滿多核CPU,而且使用方法非常簡單。
注意要用apply_async,如果落下async,就變成阻塞版本了。
processes=4是最多并發(fā)進程數(shù)量。
import
multiprocessing
import
time
def
func(msg):
for
i
in
xrange(3):
print
msg
time.sleep(1)
if
__name__
==
"__main__":
pool
=
multiprocessing.Pool(processes=4)
for
i
in
xrange(10):
msg
=
"hello
%d"
%(i)
pool.apply_async(func,
(msg,
))
pool.close()
pool.join()
print
"Sub-process(es)
done."
3、使用Pool,并需要關(guān)注結(jié)果
更多的時候,我們不僅需要多進程執(zhí)行,還需要關(guān)注每個進程的執(zhí)行結(jié)果,如下:
import multiprocessing import time def func(msg): for i in xrange(3): print msg time.sleep(1) return "done " + msg if __name__ == "__main__": pool = multiprocessing.Pool(processes=4) result = [] for i in xrange(10): msg = "hello %d" %(i) result.append(pool.apply_async(func, (msg, ))) pool.close() pool.join() for res in result: print res.get() print "Sub-process(es) done."
2014.12.25更新
根據(jù)網(wǎng)友評論中的反饋,在Windows下運行有可能崩潰(開啟了一大堆新窗口、進程),可以通過如下調(diào)用來解決:
multiprocessing.freeze_support()
簡易worker multiprocessing.Pool
多任務(wù)模型設(shè)計是一個比較復(fù)雜的邏輯,但是python對于多任務(wù)的處理卻有種種方便的類庫,不需要過多的糾結(jié)進程/線程間的操作細節(jié)。比如multiprocessing.Pool就是其中之一。
官方給的范例也很簡單。
from multiprocessing import Pool def f(x): return x*x if __name__ == '__main__': pool = Pool(processes=4) # start 4 worker processes result = pool.apply_async(f, [10]) # evaluate "f(10)" asynchronously print result.get(timeout=1) # prints "100" unless your computer is *very* slow print pool.map(f, range(10)) # prints "[0, 1, 4,..., 81]"
并未做太多的詳細解釋。正好我手頭有一段代碼,需要請求幾百個url,解析html頁面獲取一些信息,單線程for循環(huán)效率極低,因此看到了這個模塊,想用這個實現(xiàn)多任務(wù)分析,參考代碼如下:
from multiprocessing import Pool def analyse_url(url): #do something with this url return analysis_result if __name__ == '__main__': pool = Pool(processes=10) result = pool.map(analyse_url, url_list)
確實比以前單線程for循環(huán)url_list列表,一個個請求analyse_url要快得多,但是帶來的問題就是一旦pool.map沒執(zhí)行完就ctrl-c中斷程序,程序就會異常,永遠無法退出,參考stackoverflow的這個帖子,修改為以下代碼:
#result = pool.map(analyse_url, url_list) result = pool.map_async(analyse_url, url_list).get(120)
至此問題完美解決。
以上這篇Python 多進程并發(fā)操作中進程池Pool的實例就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
python base64圖片互轉(zhuǎn),解決base64字符串轉(zhuǎn)PIL圖片對象報錯:binascii.Error:
在Base64編碼中,若字符串長度不是4的倍數(shù),需在末尾添加等號作為填充,不符合此規(guī)則會導(dǎo)致在轉(zhuǎn)換為圖片時出現(xiàn)binascii.Error:Incorrectpadding錯誤,正確的填充確保編碼后的字符串可以正確轉(zhuǎn)換成圖片,避免轉(zhuǎn)換錯誤2024-09-09
淺談四種快速易用的Python數(shù)據(jù)可視化方法
這篇文章主要介紹了淺談四種快速易用的Python數(shù)據(jù)可視化方法,數(shù)據(jù)可視化,是指用圖形的方式來展現(xiàn)數(shù)據(jù),從而更加清晰有效地傳遞信息,主要方法包括圖表類型的選擇和圖表設(shè)計的準則,需要的朋友可以參考下2023-04-04
python numpy中的polyfit函數(shù)用法
這篇文章主要介紹了python numpy中的polyfit函數(shù)用法,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-04-04

