Python標(biāo)準(zhǔn)庫(kù)之多進(jìn)程(multiprocessing包)介紹
在初步了解Python多進(jìn)程之后,我們可以繼續(xù)探索multiprocessing包中更加高級(jí)的工具。這些工具可以讓我們更加便利地實(shí)現(xiàn)多進(jìn)程。
進(jìn)程池
進(jìn)程池 (Process Pool)可以創(chuàng)建多個(gè)進(jìn)程。這些進(jìn)程就像是隨時(shí)待命的士兵,準(zhǔn)備執(zhí)行任務(wù)(程序)。一個(gè)進(jìn)程池中可以容納多個(gè)待命的士兵。

“三個(gè)進(jìn)程的進(jìn)程池”
比如下面的程序:
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)
我們創(chuàng)建了一個(gè)容許5個(gè)進(jìn)程的進(jìn)程池 (Process Pool) 。Pool運(yùn)行的每個(gè)進(jìn)程都執(zhí)行f()函數(shù)。我們利用map()方法,將f()函數(shù)作用到表的每個(gè)元素上。這與built-in的map()函數(shù)類似,只是這里用5個(gè)進(jìn)程并行處理。如果進(jìn)程運(yùn)行結(jié)束后,還有需要處理的元素,那么的進(jìn)程會(huì)被用于重新運(yùn)行f()函數(shù)。除了map()方法外,Pool還有下面的常用方法。
apply_async(func,args) 從進(jìn)程池中取出一個(gè)進(jìn)程執(zhí)行func,args為func的參數(shù)。它將返回一個(gè)AsyncResult的對(duì)象,你可以對(duì)該對(duì)象調(diào)用get()方法以獲得結(jié)果。
close() 進(jìn)程池不再創(chuàng)建新的進(jìn)程
join() wait進(jìn)程池中的全部進(jìn)程。必須對(duì)Pool先調(diào)用close()方法才能join。
練習(xí)
有下面一個(gè)文件download.txt。
www.sina.com.cn
www.163.com
www.iciba.com
www.cnblogs.com
www.qq.com
www.douban.com
使用包含3個(gè)進(jìn)程的進(jìn)程池下載文件中網(wǎng)站的首頁(yè)。(你可以使用subprocess調(diào)用wget或者curl等下載工具執(zhí)行具體的下載任務(wù))
共享資源
我們?cè)赑ython多進(jìn)程初步已經(jīng)提到,我們應(yīng)該盡量避免多進(jìn)程共享資源。多進(jìn)程共享資源必然會(huì)帶來(lái)進(jìn)程間相互競(jìng)爭(zhēng)。而這種競(jìng)爭(zhēng)又會(huì)造成race condition,我們的結(jié)果有可能被競(jìng)爭(zhēng)的不確定性所影響。但如果需要,我們依然可以通過(guò)共享內(nèi)存和Manager對(duì)象這么做。

共享“資源”
共享內(nèi)存
在Linux進(jìn)程間通信中,我們已經(jīng)講述了共享內(nèi)存(shared memory)的原理,這里給出用Python實(shí)現(xiàn)的例子:
# 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[:]
這里我們實(shí)際上只有主進(jìn)程和Process對(duì)象代表的進(jìn)程。我們?cè)谥鬟M(jìn)程的內(nèi)存空間中創(chuàng)建共享的內(nèi)存,也就是Value和Array兩個(gè)對(duì)象。對(duì)象Value被設(shè)置成為雙精度數(shù)(d), 并初始化為0.0。而Array則類似于C中的數(shù)組,有固定的類型(i, 也就是整數(shù))。在Process進(jìn)程中,我們修改了Value和Array對(duì)象?;氐街鞒绦?,打印出結(jié)果,主程序也看到了兩個(gè)對(duì)象的改變,說(shuō)明資源確實(shí)在兩個(gè)進(jìn)程之間共享。
Manager
Manager對(duì)象類似于服務(wù)器與客戶之間的通信 (server-client),與我們?cè)贗nternet上的活動(dòng)很類似。我們用一個(gè)進(jìn)程作為服務(wù)器,建立Manager來(lái)真正存放資源。其它的進(jìn)程可以通過(guò)參數(shù)傳遞或者根據(jù)地址來(lái)訪問(wèn)Manager,建立連接后,操作服務(wù)器上的資源。在防火墻允許的情況下,我們完全可以將Manager運(yùn)用于多計(jì)算機(jī),從而模仿了一個(gè)真實(shí)的網(wǎng)絡(luò)情境。下面的例子中,我們對(duì)Manager的使用類似于shared memory,但可以共享更豐富的對(duì)象類型。
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()方法提供了表的共享方式。實(shí)際上你可以利用dict()來(lái)共享詞典,Lock()來(lái)共享threading.Lock(注意,我們共享的是threading.Lock,而不是進(jìn)程的mutiprocessing.Lock。后者本身已經(jīng)實(shí)現(xiàn)了進(jìn)程共享)等。 這樣Manager就允許我們共享更多樣的對(duì)象。
我們?cè)谶@里不深入講解Manager在遠(yuǎn)程情況下的應(yīng)用。有機(jī)會(huì)的話,會(huì)在網(wǎng)絡(luò)應(yīng)用中進(jìn)一步探索。
總結(jié)
Pool
Shared memory, Manager
- Python多進(jìn)程并發(fā)(multiprocessing)用法實(shí)例詳解
- Python3多進(jìn)程 multiprocessing 模塊實(shí)例詳解
- Python多進(jìn)程multiprocessing用法實(shí)例分析
- python multiprocessing多進(jìn)程變量共享與加鎖的實(shí)現(xiàn)
- python基于multiprocessing的多進(jìn)程創(chuàng)建方法
- python multiprocessing 多進(jìn)程并行計(jì)算的操作
- 簡(jiǎn)單學(xué)習(xí)Python多進(jìn)程Multiprocessing
- Python使用multiprocessing實(shí)現(xiàn)多進(jìn)程的詳細(xì)步驟記錄
相關(guān)文章
Python中命令行參數(shù)argparse模塊的使用
argparse是python自帶的命令行參數(shù)解析包,可以用來(lái)方便的服務(wù)命令行參數(shù)。本文將通過(guò)示例和大家詳細(xì)講講argparse的使用,需要的可以參考一下2023-02-02
pyinstaller打包后,配置文件無(wú)法正常讀取的解決
這篇文章主要介紹了pyinstaller打包后,配置文件無(wú)法正常讀取的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02
Python使用configparser庫(kù)讀取配置文件
這篇文章主要介紹了Python使用configparser庫(kù)讀取配置文件,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02
Python列表list操作相關(guān)知識(shí)小結(jié)
今天,本喵帶大家仔細(xì)溫習(xí)一下Python的列表,溫故而知新,不亦說(shuō)乎,需要的朋友可以參考下2020-01-01
Python繪制數(shù)據(jù)動(dòng)態(tài)圖的方法詳解
這篇文章主要為大家詳細(xì)介紹了如何利用Python語(yǔ)言繪制好看的數(shù)據(jù)動(dòng)態(tài)圖,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起動(dòng)手嘗試一下2022-07-07
python中將函數(shù)賦值給變量時(shí)需要注意的一些問(wèn)題
變量賦值是我們?cè)谌粘i_發(fā)中經(jīng)常會(huì)遇到的一個(gè)問(wèn)題,下面這篇文章主要給大家介紹了關(guān)于python中將函數(shù)賦值給變量時(shí)需要注意的一些問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-08-08
讓Django支持Sql Server作后端數(shù)據(jù)庫(kù)的方法
今天小編就為大家分享一篇讓Django支持Sql Server作后端數(shù)據(jù)庫(kù)的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-05-05

