Python程式專題4:程式池Pool

Mark發表於2019-02-16

上一篇文章:Python程式專題3:繼承Process來建立程式
下一篇文章:Python程式專題5:程式間通訊

當我們需要建立大量的程式時,利用multiprocessing模組提供的Pool來建立程式。

程式初始化時,會指定一個最大程式數量,當有新的請求需要建立程式時,如果此時程式池還沒有到達設定的最大程式數,該程式池就會建立新的程式來處理該請求,並把該程式放到程式池中,如果程式池已經達到最大數量,請求就會等待,知道程式池中程式數量減少,才會新建程式來執行請求。

  • 語法
pool=Pool(numprocess,initializer,initargs)
numproxess:需要建立的程式個數,如果忽略將使用cpu_count()的值。即系統上的CPU數量。
initializer:每個程式啟動時都要呼叫的物件。
initargs:為
initalizer傳遞的引數。
  • 常用方法

multiprocessing.Pool常用函式解析:

apply_async(要呼叫的方法,引數列表,關鍵字引數列表):使用非阻塞方式呼叫指定方法,並行執行(同時執行)

apply(要呼叫的方法,引數列表,關鍵字引數列表):使用阻塞方式呼叫指定方法,,阻塞方式就是要等上一個程式退出後,下一個程式才開始執行。

close():關閉程式池,不再接受進的程式請求,但已經接受的程式還是會繼續執行。

terminate():不管程任務是否完成,立即結束。

join():主程式堵塞(就是不執行join下面的語句),直到子程式結束,注意,該方法必須在close或terminate之後使用。

pool.map(func,iterable,chunksize):將可呼叫物件func應用給iterable的每一項,然後以列表形式返回結果,
通過將iterable劃分為多塊,並分配給工作程式,可以並行執行。chunksize指定每塊中的項數,
如果資料量較大,可以增大chunksize的值來提升效能。

pool.map_async(func,iterable,chunksize,callback):與map方法不同之處是返回結果是非同步的,
如果callback指定,當結果可用時,結果會呼叫callback。

pool.imap(func,iterable,chunksize):與map()方法的不同之處是返回迭代器而非列表。

pool.imap_unordered(func,iterable,chunksize):與imap()不同之處是:結果的順序是根據從工作程式接收到的時間而定的。

pool.get(timeout):如果沒有設定timeout,將會一直等待結果,
如果設定了timeout,超過timeout將引發multiprocessing.TimeoutError異常。

pool.ready():如果呼叫完成,返回True

pool.successful():如果呼叫完成並且沒有引發異常,返回True,如果在結果就緒之前呼叫,jiang引發AssertionError異常。

pool.wait(timeout):等待結果變為可用,timeout為等待時間。
  • 例項1:阻塞與非阻塞對比
#阻塞與非阻塞對比
from multiprocessing import Pool
import os
import time
import random#用來生成隨機數

def test1(name):
    print("%s執行中,pid=%d,父程式:%d"%(name,os.getpid(),os.getppid()))
    t_start=time.time()
    #random.random()會生成一個0——1的浮點數
    time.sleep(random.random()*3)
    t_end=time.time()
    print("%s執行時間:%0.2f秒"%(name,t_end-t_start))

pool=Pool(5)#設定執行緒池中最大執行緒數量為5
for xx in range(0,7):
    #非阻塞執行
    pool.apply_async(test1,("mark"+str(id),))
print("--start1--")
pool.close()#關閉執行緒池,關閉後不再接受進的請求
pool.join()#等待程式池所有程式都執行完畢後,開始執行下面語句
print("--end1--")
print("*"*30)
pool=Pool(5)#設定執行緒池中最大執行緒數量為5
for xx in range(0,7):
    #阻塞執行
    pool.apply(test1,("mark"+str(id),))
print("--start2--")
pool.close()#關閉執行緒池,關閉後不再接受進的請求
pool.join()#等待程式池所有程式都執行完畢後,開始執行下面語句
print("--end2--")

結果:

--start1--
mark<built-in function id>執行中,pid=28631,父程式:28626
mark<built-in function id>執行中,pid=28632,父程式:28626
mark<built-in function id>執行中,pid=28633,父程式:28626
mark<built-in function id>執行中,pid=28634,父程式:28626
mark<built-in function id>執行中,pid=28636,父程式:28626
mark<built-in function id>執行時間:0.27秒
mark<built-in function id>執行中,pid=28633,父程式:28626
mark<built-in function id>執行時間:0.32秒
mark<built-in function id>執行中,pid=28634,父程式:28626
mark<built-in function id>執行時間:0.18秒
mark<built-in function id>執行時間:0.55秒
mark<built-in function id>執行時間:1.78秒
mark<built-in function id>執行時間:1.92秒
mark<built-in function id>執行時間:2.71秒
--end1--
******************************
mark<built-in function id>執行中,pid=28647,父程式:28626
mark<built-in function id>執行時間:0.70秒
mark<built-in function id>執行中,pid=28648,父程式:28626
mark<built-in function id>執行時間:1.66秒
mark<built-in function id>執行中,pid=28649,父程式:28626
mark<built-in function id>執行時間:2.87秒
mark<built-in function id>執行中,pid=28650,父程式:28626
mark<built-in function id>執行時間:2.68秒
mark<built-in function id>執行中,pid=28651,父程式:28626
mark<built-in function id>執行時間:1.42秒
mark<built-in function id>執行中,pid=28647,父程式:28626
mark<built-in function id>執行時間:1.20秒
mark<built-in function id>執行中,pid=28648,父程式:28626
mark<built-in function id>執行時間:2.01秒
--start2--
--end2--
  • 例項2:利用程式池遍歷目錄

檢視下面例項前,先來熟悉一下我們需要用到的一些知識。

os.walk(top,topdown=true,onerrorNone,followlinks=false):遍歷目錄地址,返回一個三元組(root,dirs,files)

top:想要遍歷的目錄

root:當前正在遍歷的資料夾地址。

dirs:是一個list:當前資料夾下所有目錄的名字(不包括子目錄)

files:也是一個list,當前資料夾下所有檔案的名字(不包括子目錄檔案)

topdown:預設為True:優先遍歷top目錄,為false會優先遍歷top的子目錄。

onerror:指定一個當方法執行異常時需要呼叫的方法。

followlinks:預設為True:會遍歷目錄環境下的快捷方式實際指向目錄。

程式碼:

#遍歷目錄檔案並求取SHA512的摘要值
import os
import multiprocessing
import hashlib

#定義程式大小
POOLSIZE=2 #工作程式的數量
#可以讀取的緩衝區大小
BUFSIZE=8196

def mark(filename):
    try:
        f=open(filename,"rb")
    except IOError:
        return None
    digest=hashlib.sha512()
    while True:
        chunk=f.read(BUFSIZE)
        if not chunk:break
        digest.update(chunk)
    f.close()
    return filename,digest.digest()



def build_map(dir):
    #定義程式
    pool=multiprocessing.Pool(POOLSIZE)


    #os.path.join:拼接檔案路徑
    #根據檔案目錄和名稱拼接
    all_files=(os.path.join(root,name)
               #迴圈遍歷當前目錄
               for root,dirs,files in os.walk(dir)
                   #取出當前目錄下檔名
                   for name in files)

    #dict方法用於將結果轉化成字典
    map=dict(pool.imap_unordered(mark,all_files,20))
    pool.close()
    return map


if __name__=="__main__":
    digest_map=build_map("/Users/zhaolixiang/Desktop/python/test1/程式")
    for item in  digest_map:
        print("檔案目錄:",item)
        print("SHA512摘要值:",digest_map[item])
    #個數
    print(len(digest_map))

結果

檔案目錄: /Users/zhaolixiang/Desktop/python/test1/程式/1、fork建立子執行緒.py
SHA512摘要值: b`x9eYLSxe5xb6xd2xecxd4&xa9xff~m?x87xd2Nxea39Gxe1x8fx9cdx83@x06/Bnxddx1exb5xe0jx10xd1xc9=xfd;y]x8dnR)xbdtxb8xc8xb46rExf8xd7t.xaexbbxe9`
檔案目錄: /Users/zhaolixiang/Desktop/python/test1/程式/8、JoinableQueue的生產者與消費者.py
SHA512摘要值: b`xfe4x18xee8xd1x97xe7vx86}xe6qnx13xf9Dxf1Xxe3xabx94xebx96xfbxedWx0bOn$x14d/+rx9bx0bxc1xd4x03xadxcbbxf7x8dxd5Ccx03yxd1xb4x801,?,rIXxa28xd7`
檔案目錄: /Users/zhaolixiang/Desktop/python/test1/程式/10、管道:返回資料.py
SHA512摘要值: b`x85xb1Cxe56x80x1dsx84txf6x95xcbx1d[xdaxe4}n)Y<xd5x10=x94x88xd8xafxccr@eCxc4!xc1xb70x9fzxc6xb1xb9xf6xc4xcexd7x02x86<xc8Ux0fx8bqxdax18ydxa3Kx8bxd6`
檔案目錄: /Users/zhaolixiang/Desktop/python/test1/程式/11、程式池.py
SHA512摘要值: b`bBxf4lxccxd5xaetrxc1x816xe5xfc;tx85x86xe5xd3x9e~SH]xe6xcbdxc9xfexe9xfbxfcxeb)Axd2ox8cOxbcx1etxe9xe92^xb5x10xe1xf4xc9\_x0cx8cxa7qxf4(x13Mxbe7`
檔案目錄: /Users/zhaolixiang/Desktop/python/test1/程式/2、multiprocessing.py
SHA512摘要值: b”mxb2xb5x00M1=qx86xb9Gxf9x02xb1x18xfax08xe7,.xefxff5xebt,nx17xbfB-xc6xc2x9dVxf9x88xa7xd8x1ex9b)x86Nxd5xab x89xa0J}xa9xdcxbcx06mx03xa7x87.x17xcb`x93″
檔案目錄: /Users/zhaolixiang/Desktop/python/test1/程式/6、驗證:put方法會阻塞.py
SHA512摘要值: b`xa3x80x86xf6xc9xb8x0eOB 5xd0x949xfdxc2yx9axc7xcax9dxbc%xa1xe6_xfax84xb6x02$xf7x10xbbxb9Nxfbxdexc8xbe6F xd6x87xacxb2xf5x94x0cxedxe0.xf9Txdax91`;xd7x90x86`
檔案目錄: /Users/zhaolixiang/Desktop/python/test1/程式/7、closse方法、get方法、put方法簡單使用.py
SHA512摘要值: b`lx98wx8fTx15xdfTx19x91^:xc5xa3x8dxf4x1ex9cx91Exe4xe7xbfxecVx1ex1bx19xa0ix96Lxc6xc4r.x9bxecx88xe9rxfeOx8bxdfAx90x7f6?xe7x1d8xa6Nx07xdex8dxb6xe7#x02p`
檔案目錄: /Users/zhaolixiang/Desktop/python/test1/程式/5、程式池.py
SHA512摘要值: b`xc2xf75x04xbaxa5Xxccx81x88xffxbazxd81@x0bQJ%xbbx15xf3`Qx9a4}xc0x07xa2&axc0x00x0c%xb4[xd2ex18x04x14ytx0cxb0xacx1dxf5xfbxe0xc7xb6$xd2xf1xd9sePx08`
檔案目錄: /Users/zhaolixiang/Desktop/python/test1/程式/3、multiprocessing.py
SHA512摘要值: b`x04N4Dxd5xab}xcfx03xe6x0fVx0fx910x91xe4x81,xbb-xdfxb36Ixf9!x84Axdf.xf3HVxfdx86:x0bx81<+ex00xd1x17uxf5hxb34FxfexebFxf5x1bxc3x8d`Axa0Ax02x10`
檔案目錄: /Users/zhaolixiang/Desktop/python/test1/程式/9、管道.py
SHA512摘要值: b“xdbx8dx90Vx04=x0cxf9x9cxf7{x8fxcax9fxccxb8Dx97xecx82(xd4x9ax84xdb<xb8+x16xd7xecx057xe0x07xe9xc3xdccxe3 t#vxecxb5xe3npxc7~x95xd0J-cxb1xefx03.?xx12`
檔案目錄: /Users/zhaolixiang/Desktop/python/test1/程式/4、繼承Process建立程式.py
SHA512摘要值: b`2xc1xa0x1fxd7xd6xb2x1c}x14xdedx8fxdbxedxd0x91mxc1,xb9xdd?TbXx04#2xfcxb8xbfurxabxfcFcx17x18xc7)sYx82x0exea{5x87xf3x8fcxbaPx91r0xefxabLxa8x1ex15`
11

相關文章