Python標準庫11 多進程探索 (multiprocessing包)

做者:Vamei 出處:http://www.cnblogs.com/vamei 歡迎轉載,也請保留這段聲明。謝謝!html

 

初步瞭解Python多進程以後,咱們能夠繼續探索multiprocessing包中更加高級的工具。這些工具可讓咱們更加便利地實現多進程。python

 

進程池

進程池 (Process Pool)能夠建立多個進程。這些進程就像是隨時待命的士兵,準備執行任務(程序)。一個進程池中能夠容納多個待命的士兵。數組

 

「三個進程的進程池」服務器

 

 

好比下面的程序:網絡

import multiprocessing as mul

def f(x):
    return x**2

pool = mul.Pool(5)
rel  = pool.map(f,[1,2,3,4,5,6,7,8,9,10])
print(rel)

咱們建立了一個允許5個進程的進程池 (Process Pool) 。Pool運行的每一個進程都執行f()函數。咱們利用map()方法,將f()函數做用到表的每一個元素上。這與built-in的map()函數相似,只是這裏用5個進程並行處理。若是進程運行結束後,還有須要處理的元素,那麼的進程會被用於從新運行f()函數。除了map()方法外,Pool還有下面的經常使用方法。app

apply_async(func,args)  從進程池中取出一個進程執行func,args爲func的參數。它將返回一個AsyncResult的對象,你能夠對該對象調用get()方法以得到結果。curl

close()  進程池再也不建立新的進程async

join()   wait進程池中的所有進程。必須對Pool先調用close()方法才能join。函數

 

練習工具

有下面一個文件download.txt。

www.sina.com.cn
www.163.com
www.iciba.com
www.cnblogs.com
www.qq.com
www.douban.com

使用包含3個進程的進程池下載文件中網站的首頁。(你能夠使用subprocess調用wget或者curl等下載工具執行具體的下載任務)

 

共享資源

咱們在Python多進程初步已經提到,咱們應該儘可能避免多進程共享資源。多進程共享資源必然會帶來進程間相互競爭。而這種競爭又會形成race condition,咱們的結果有可能被競爭的不肯定性所影響。但若是須要,咱們依然能夠經過共享內存和Manager對象這麼作。

 

共享「資源」

共享內存

Linux進程間通訊中,咱們已經講述了共享內存(shared memory)的原理,這裏給出用Python實現的例子:

# modified from official documentation
import multiprocessing

def f(n, a):
    n.value   = 3.14
    a[0]      = 5

num   = multiprocessing.Value('d', 0.0)
arr   = multiprocessing.Array('i', range(10))

p = multiprocessing.Process(target=f, args=(num, arr))
p.start()
p.join()

print num.value
print arr[:]

這裏咱們實際上只有主進程和Process對象表明的進程。咱們在主進程的內存空間中建立共享的內存,也就是ValueArray兩個對象。對象Value被設置成爲雙精度數(d), 並初始化爲0.0。而Array則相似於C中的數組,有固定的類型(i, 也就是整數)。在Process進程中,咱們修改了Value和Array對象。回到主程序,打印出結果,主程序也看到了兩個對象的改變,說明資源確實在兩個進程之間共享。

 

Manager

Manager對象相似於服務器與客戶之間的通訊 (server-client),與咱們在Internet上的活動很相似。咱們用一個進程做爲服務器,創建Manager來真正存放資源。其它的進程能夠經過參數傳遞或者根據地址來訪問Manager,創建鏈接後,操做服務器上的資源。在防火牆容許的狀況下,咱們徹底能夠將Manager運用於多計算機,從而模仿了一個真實的網絡情境。下面的例子中,咱們對Manager的使用相似於shared memory,但能夠共享更豐富的對象類型。

import multiprocessing

def f(x, arr, l):
    x.value = 3.14
    arr[0] = 5
    l.append('Hello')

server = multiprocessing.Manager()
x    = server.Value('d', 0.0)
arr  = server.Array('i', range(10))
l    = server.list()

proc = multiprocessing.Process(target=f, args=(x, arr, l))
proc.start()
proc.join()

print(x.value)
print(arr)
print(l)

Manager利用list()方法提供了表的共享方式。實際上你能夠利用dict()來共享詞典,Lock()來共享threading.Lock(注意,咱們共享的是threading.Lock,而不是進程的mutiprocessing.Lock。後者自己已經實現了進程共享)等。 這樣Manager就容許咱們共享更多樣的對象。

 

咱們在這裏不深刻講解Manager在遠程狀況下的應用。有機會的話,會在網絡應用中進一步探索。

 

總結

Pool

Shared memory, Manager

相關文章
相關標籤/搜索