python進(jìn)階——多進(jìn)程

因為GIL(全局解釋器鎖)的限制(GIL是用來保證在任意時刻只能有一個控制線程在執(zhí)行)球凰,所以python中的多線程并非真正的多線程。只有python程序是I/O密集型應(yīng)用時,多線程才會對運行效率有顯著提高(因在等待I/O的時抚吠,會釋放GIL允許其他線程繼續(xù)執(zhí)行),而在計算密集型應(yīng)用中弟胀,多線程并沒有什么用處楷力。考慮到要充分利用多核CPU的資源邮利,允許python可以并行處理一些任務(wù)弥雹,這里就用到了python多進(jìn)程編程了垃帅。multiprocessing是python中的多進(jìn)程模塊延届,使用這個模塊可以方便地進(jìn)行多進(jìn)程應(yīng)用程序開發(fā)。multiprocessing模塊中提供了:Process贸诚、Pool方庭、Queue、Manager等組件酱固。

1 Process類

1.1 構(gòu)造方法

def __init__(self, group=None, target=None, name=None, args=(), kwargs={})

group:進(jìn)程所屬組械念,基本不用
target:進(jìn)程調(diào)用對象(可以是一個函數(shù)名,也可以是一個可調(diào)用的對象(實現(xiàn)了__call__方法的類))
args:調(diào)用對象的位置參數(shù)元組
name:別名
kwargs:調(diào)用對象的關(guān)鍵字參數(shù)字典

1.2 實例方法

is_alive():返回進(jìn)程是否在運行
start():啟動進(jìn)程运悲,等待CPU調(diào)度
join([timeout]):阻塞當(dāng)前上下文環(huán)境龄减,直到調(diào)用此方法的進(jìn)程終止或者到達(dá)指定timeout
terminate():不管任務(wù)是否完成,立即停止該進(jìn)程
run():start()調(diào)用該方法班眯,當(dāng)實例進(jìn)程沒有傳入target參數(shù)希停,stat()將執(zhí)行默認(rèn)的run()方法

1.3 屬性

authkey
daemon:守護(hù)進(jìn)程標(biāo)識,在start()調(diào)用之前可以對其進(jìn)行修改
exitcode:進(jìn)程的退出狀態(tài)碼
name:進(jìn)程名
pid:進(jìn)程id

1.4 實例

實例一:傳入的target為一個函數(shù)

#!/usr/bin/python
#coding=utf-8

import time
import random
from multiprocessing import Process

def foo(i):
    print time.ctime(), "process the %d begin ......" %i
    time.sleep(random.uniform(1,3))
    print time.ctime(), "process the %d end !!!!!!" %i

if __name__ == "__main__":
    print time.ctime(), "process begin......"
    
    p_lst = list()
    for i in range(4):
        p_lst.append(Process(target=foo, args=(i,)))    #創(chuàng)建4個子進(jìn)程
    #啟動子進(jìn)程
    for p in p_lst:
        p.start()
    #等待子進(jìn)程全部結(jié)束
    for p in p_lst:
        p.join()

    print time.ctime(), "process end!!!!!"   

實例二:傳入的target為一個可調(diào)用對象

#!/usr/bin/python
#coding=utf-8

import time
import random
from multiprocessing import Process

class Foo(object):
    def __init__(self, i):
        self.i = i

    def __call__(self):
        '''
        使Foo的實例對象成為可調(diào)用對象
        '''                                                                                                        
        print time.ctime(), "process the %d begin ......" %self.i
        time.sleep(random.uniform(1,3))
        print time.ctime(), "process the %d end !!!!!!" %self.i

if __name__ == "__main__":
    print time.ctime(), "process begin......"
    
    p_lst = list()
    for i in range(4):
        p_lst.append(Process(target=Foo(i)))    #創(chuàng)建4個子進(jìn)程
    #啟動子進(jìn)程
    for p in p_lst:
        p.start()
    #等待子進(jìn)程全部結(jié)束
    for p in p_lst:
        p.join()

    print time.ctime(), "process end!!!!!"

實例三:派生Process子類署隘,并創(chuàng)建子類的實例

#!/usr/bin/python                                                                                                  
#coding=utf-8

import time
import random
from multiprocessing import Process

class MyProcess(Process):

    def __init__(self, i):
        Process.__init__(self)
        self.i = i

    def run(self):
        '''
        #重寫run方法宠能,當(dāng)調(diào)用start方法時,就會調(diào)用當(dāng)前重寫的run方法中的程序
        '''
        print time.ctime(), "process the %d begin ......" %self.i
        time.sleep(random.uniform(1,3))
        print time.ctime(), "process the %d end !!!!!!" %self.i

if __name__ == "__main__":
    print time.ctime(), "process begin......"

    p_lst = list()
    for i in range(4):
        p_lst.append(MyProcess(i))  #創(chuàng)建4個子進(jìn)程
    #啟動子進(jìn)程
    for p in p_lst:
        p.start()
    #等待子進(jìn)程全部結(jié)束
    for p in p_lst:
        p.join()

    print time.ctime(), "process end!!!!!"

2 Pool類

當(dāng)使用Process類管理非常多(幾十上百個)的進(jìn)程時磁餐,就會顯得比較繁瑣违崇,這是就可以使用Pool(進(jìn)程池)來對進(jìn)程進(jìn)行統(tǒng)一管理。當(dāng)池中進(jìn)程已滿時诊霹,有新進(jìn)程請求執(zhí)行時羞延,就會被阻塞,直到池中有進(jìn)程執(zhí)行結(jié)束脾还,新的進(jìn)程請求才會被放入池中并執(zhí)行肴楷。

2.1 構(gòu)造方法

def __init__(self, processes=None, initializer=None, initargs=(),                 maxtasksperchild=None)

processes:池中可容納的工作進(jìn)程數(shù)量,默認(rèn)情況使用os.cpu_count()返回的數(shù)值荠呐,一般默認(rèn)即可
其他參數(shù)暫不清楚有什么用處......

2.2 實例方法

apply(self, func, args=(), kwds={}):阻塞型進(jìn)程池赛蔫,會阻塞主進(jìn)程砂客,直到工作進(jìn)程全部退出,一般不用這個
apply_async(self, func, args=(), kwds={}, callback=None):非阻塞型進(jìn)程池
map(self, func, iterable, chunksize=None):與內(nèi)置map行為一致呵恢,它會阻塞主進(jìn)程鞠值,直到map運行結(jié)束
map_async(self, func, iterable, chunksize=None, callback=None):非阻塞版本的map
close():關(guān)閉進(jìn)程池,不在接受新任務(wù)
terminate():結(jié)束工作進(jìn)程
join():阻塞主進(jìn)程等待子進(jìn)程退出渗钉,該方法必須在close或terminate之后執(zhí)行

2.3 實例

#!/usr/bin/python
#coding=utf-8

import time
import random
from multiprocessing import Pool

def foo(i):
    print time.ctime(), "process the %d begin ......" %i
    time.sleep(random.uniform(1,3))
    print time.ctime(), "process the %d end !!!!!!" %i

if __name__ == "__main__":

    print time.ctime(), "process begin......"
    pool = Pool(processes = 2)  #設(shè)置進(jìn)程池中最大并行工作進(jìn)程數(shù)為2                                                 
    for i in range(4):
        pool.apply_async(foo, args=(i,))    #提交4個子進(jìn)程任務(wù)

    pool.close()
    pool.join()

    print time.ctime(), "process end!!!!!"

結(jié)果:

Fri Nov 18 13:57:22 2016 process begin......
Fri Nov 18 13:57:22 2016 process the 0 begin ......
Fri Nov 18 13:57:22 2016 process the 1 begin ......
Fri Nov 18 13:57:23 2016 process the 1 end !!!!!!
Fri Nov 18 13:57:23 2016 process the 2 begin ......
Fri Nov 18 13:57:24 2016 process the 0 end !!!!!!
Fri Nov 18 13:57:24 2016 process the 3 begin ......
Fri Nov 18 13:57:25 2016 process the 2 end !!!!!!
Fri Nov 18 13:57:25 2016 process the 3 end !!!!!!
Fri Nov 18 13:57:25 2016 process end!!!!!

3 Queue類

Queue主要提供進(jìn)程間通信以及共享數(shù)據(jù)等功能彤恶。除Queue外還可以使用Pipes實現(xiàn)進(jìn)程間通信(Pipes是兩個進(jìn)程間進(jìn)行通信)

3.1 構(gòu)造方法

def __init__(self, maxsize=0)

maxsize:用于設(shè)置隊列最大長度,當(dāng)為maxsize<=0時鳄橘,隊列的最大長度會被設(shè)置為一個非常大的值(我的系統(tǒng)中隊列最大長度被設(shè)置為2147483647)

3.2 實例方法

put(self, obj, block=True, timeout=None)

1声离、block為True,若隊列已滿瘫怜,并且timeout為正值术徊,該方法會阻塞timeout指定的時間,直到隊列中有出現(xiàn)剩余空間鲸湃,如果超時赠涮,會拋出Queue.Full異常
2、block為False暗挑,若隊列已滿笋除,立即拋出Queue.Full異常

get(self, block=True, timeout=None)

block為True,若隊列為空炸裆,并且timeout為正值垃它,該方法會阻塞timeout指定的時間,直到隊列中有出現(xiàn)新的數(shù)據(jù)烹看,如果超時国拇,會拋出Queue.Empty異常
block為False,若隊列為空听系,立即拋出Queue.Empty異常

3.3 實例

#!/usr/bin/python
#coding=utf-8

import time
import random
from multiprocessing import Process, Queue

def write(q):
    for value in "abcd":
        print time.ctime(), "put %s to queue" %value
        q.put(value)
        time.sleep(random.random())

def read(q):
    while True:
        value = q.get()
        print time.ctime(), "get %s from queue" %value

if __name__ == "__main__":
    #主進(jìn)程創(chuàng)建Queue贝奇,并作為參數(shù)傳遞給子進(jìn)程
    q = Queue()
    pw = Process(target=write, args=(q,))
    pr = Process(target=read, args=(q,))
    #啟動子進(jìn)程pw,往Queue中寫入
    pw.start()
    #啟動子進(jìn)程pr靠胜,從Queue中讀取
    pr.start()
    #等待寫進(jìn)程執(zhí)行結(jié)束
    pw.join()
    #終止讀取進(jìn)程                                                                                                  
    pr.terminate()

運行結(jié)果:

Fri Nov 18 15:04:13 2016 put a to queue
Fri Nov 18 15:04:13 2016 get a from queue
Fri Nov 18 15:04:13 2016 put b to queue
Fri Nov 18 15:04:13 2016 get b from queue
Fri Nov 18 15:04:13 2016 put c to queue
Fri Nov 18 15:04:13 2016 get c from queue
Fri Nov 18 15:04:13 2016 put d to queue
Fri Nov 18 15:04:13 2016 get d from queue

4 Manager類

Manager是進(jìn)程間數(shù)據(jù)共享的高級接口掉瞳。
Manager()返回的manager對象控制了一個server進(jìn)程,此進(jìn)程包含的python對象可以被其他的進(jìn)程通過proxies來訪問浪漠。從而達(dá)到多進(jìn)程間數(shù)據(jù)通信且安全陕习。Manager支持的類型有l(wèi)ist, dict, Namespace, Lock, RLock, Semaphore, BoundedSemaphore, Condition, Event, Queue, Value和Array。
如下是使用Manager管理一個用于多進(jìn)程共享的dict數(shù)據(jù)

#!/usr/bin/python
#coding=utf-8

import time
import random
from multiprocessing import Manager, Pool

def worker(d, key, value):
    print time.ctime(), "insert the k-v pair to dict begin: {%d: %d}" %(key, value)
    time.sleep(random.uniform(1,2))
    d[key] = value  #訪問共享數(shù)據(jù)
    print time.ctime(), "insert the k-v pair to dict end: {%d: %d}" %(key, value)


if __name__ == "__main__":
    print time.ctime(), "process for manager begin"
    mgr = Manager()
    d = mgr.dict()
    pool = Pool(processes=4)                                                                                       
    for i in range(10):
        pool.apply_async(worker, args=(d, i, i*i))

    pool.close()
    pool.join()
    print "Result:"
    print d
    print time.ctime(), "process for manager end"

運行結(jié)果

Fri Nov 18 16:36:19 2016 process for manager begin
Fri Nov 18 16:36:19 2016 insert the k-v pair to dict begin: {0: 0}
Fri Nov 18 16:36:19 2016 insert the k-v pair to dict begin: {1: 1}
Fri Nov 18 16:36:19 2016 insert the k-v pair to dict begin: {2: 4}
Fri Nov 18 16:36:19 2016 insert the k-v pair to dict begin: {3: 9}
Fri Nov 18 16:36:20 2016 insert the k-v pair to dict end: {3: 9}
Fri Nov 18 16:36:20 2016 insert the k-v pair to dict begin: {4: 16}
Fri Nov 18 16:36:20 2016 insert the k-v pair to dict end: {0: 0}
Fri Nov 18 16:36:20 2016 insert the k-v pair to dict begin: {5: 25}
Fri Nov 18 16:36:21 2016 insert the k-v pair to dict end: {2: 4}
Fri Nov 18 16:36:21 2016 insert the k-v pair to dict begin: {6: 36}
Fri Nov 18 16:36:21 2016 insert the k-v pair to dict end: {1: 1}
Fri Nov 18 16:36:21 2016 insert the k-v pair to dict begin: {7: 49}
Fri Nov 18 16:36:21 2016 insert the k-v pair to dict end: {5: 25}
Fri Nov 18 16:36:21 2016 insert the k-v pair to dict begin: {8: 64}
Fri Nov 18 16:36:22 2016 insert the k-v pair to dict end: {4: 16}
Fri Nov 18 16:36:22 2016 insert the k-v pair to dict begin: {9: 81}
Fri Nov 18 16:36:23 2016 insert the k-v pair to dict end: {8: 64}
Fri Nov 18 16:36:23 2016 insert the k-v pair to dict end: {6: 36}
Fri Nov 18 16:36:23 2016 insert the k-v pair to dict end: {7: 49}
Fri Nov 18 16:36:23 2016 insert the k-v pair to dict end: {9: 81}
Result:
{0: 0, 1: 1, 2: 4, 3: 9, 4: 16, 5: 25, 6: 36, 7: 49, 8: 64, 9: 81}
Fri Nov 18 16:36:23 2016 process for manager end
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末址愿,一起剝皮案震驚了整個濱河市该镣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌响谓,老刑警劉巖损合,帶你破解...
    沈念sama閱讀 206,482評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件省艳,死亡現(xiàn)場離奇詭異,居然都是意外死亡嫁审,警方通過查閱死者的電腦和手機(jī)跋炕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來律适,“玉大人辐烂,你說我怎么就攤上這事∥婊撸” “怎么了纠修?”我有些...
    開封第一講書人閱讀 152,762評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長厂僧。 經(jīng)常有香客問我扣草,道長,這世上最難降的妖魔是什么吁系? 我笑而不...
    開封第一講書人閱讀 55,273評論 1 279
  • 正文 為了忘掉前任德召,我火速辦了婚禮白魂,結(jié)果婚禮上汽纤,老公的妹妹穿的比我還像新娘。我一直安慰自己福荸,他們只是感情好蕴坪,可當(dāng)我...
    茶點故事閱讀 64,289評論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著敬锐,像睡著了一般背传。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上台夺,一...
    開封第一講書人閱讀 49,046評論 1 285
  • 那天径玖,我揣著相機(jī)與錄音,去河邊找鬼颤介。 笑死梳星,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的滚朵。 我是一名探鬼主播冤灾,決...
    沈念sama閱讀 38,351評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼辕近!你這毒婦竟也來了韵吨?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,988評論 0 259
  • 序言:老撾萬榮一對情侶失蹤移宅,失蹤者是張志新(化名)和其女友劉穎归粉,沒想到半個月后椿疗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,476評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡糠悼,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,948評論 2 324
  • 正文 我和宋清朗相戀三年变丧,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绢掰。...
    茶點故事閱讀 38,064評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡痒蓬,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出滴劲,到底是詐尸還是另有隱情攻晒,我是刑警寧澤,帶...
    沈念sama閱讀 33,712評論 4 323
  • 正文 年R本政府宣布班挖,位于F島的核電站鲁捏,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏萧芙。R本人自食惡果不足惜给梅,卻給世界環(huán)境...
    茶點故事閱讀 39,261評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望双揪。 院中可真熱鬧动羽,春花似錦、人聲如沸渔期。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽疯趟。三九已至拘哨,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間信峻,已是汗流浹背倦青。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留盹舞,地道東北人产镐。 一個月前我還...
    沈念sama閱讀 45,511評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像矾策,于是被迫代替她去往敵國和親磷账。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,802評論 2 345

推薦閱讀更多精彩內(nèi)容

  • @(python)[筆記] 目錄 一、什么是進(jìn)程 1.1 進(jìn)程的概念 進(jìn)程的概念起源于操作系統(tǒng),是操作系統(tǒng)最核心的...
    CaiGuangyin閱讀 1,250評論 0 9
  • 一绰咽、進(jìn)程的概念 相信很多同學(xué)都聽說過windows菇肃、linux,MacOS都是多任務(wù)取募,多用戶的操作系統(tǒng)琐谤。那什么是多...
    轉(zhuǎn)身后的那一回眸閱讀 972評論 0 1
  • 1.1.1多任務(wù)的引入 什么叫“多任務(wù)”呢?簡單地說玩敏,就是操作系統(tǒng)可以同時運行多個任務(wù)斗忌。打個比方,你一邊在用瀏覽器...
    PythonMaO閱讀 465評論 0 1
  • 1.進(jìn)程 1.1多線程的引入 現(xiàn)實生活中 有很多的場景中的事情是同時進(jìn)行的旺聚,比如開車的時候手和腳共同來駕駛汽車织阳,再...
    TENG書閱讀 495評論 0 0
  • 1.進(jìn)程 1.多任務(wù)的引入 有很多的場景中的事情是同時進(jìn)行的,比如開車的時候手和腳共同來駕駛汽車砰粹,再比如唱歌跳舞也...
    一只寫程序的猿閱讀 573評論 0 1