python 中的multiprocessing 模組

來源:互聯網
上載者:User

標籤:ict   should   ddc   檔案描述符   pip   div   put   size   __name__   

multiprocessing.Pipe([duplex])
返回2個連線物件(conn1, conn2),代表管道的兩端,預設是雙向通訊.如果duplex=False,conn1隻能用來接收訊息,conn2隻能用來發送訊息.不同於os.open之處在於os.pipe()返回2個檔案描述符(r, w),表示可讀的和可寫的

執行個體如下:

#!/usr/bin/python#coding=utf-8import osfrom multiprocessing import Process, Pipedef send(pipe):    pipe.send([‘spam‘] + [42, ‘egg‘])    pipe.close()def talk(pipe):    pipe.send(dict(name = ‘Bob‘, spam = 42))    reply = pipe.recv()    print(‘talker got:‘, reply)if __name__ == ‘__main__‘:    (con1, con2) = Pipe()    sender = Process(target = send, name = ‘send‘, args = (con1, ))    sender.start()    print "con2 got: %s" % con2.recv()#從send收到訊息    con2.close()    (parentEnd, childEnd) = Pipe()    child = Process(target = talk, name = ‘talk‘, args = (childEnd,))    child.start()    print(‘parent got:‘, parentEnd.recv())    parentEnd.send({x * 2 for x in ‘spam‘})    child.join()    print(‘parent exit‘)

 

輸出如下:

con2 got: [‘spam‘, 42, ‘egg‘](‘parent got:‘, {‘name‘: ‘Bob‘, ‘spam‘: 42})(‘talker got:‘, set([‘ss‘, ‘aa‘, ‘pp‘, ‘mm‘]))parent exit

  

multiprocessing中使用子進程概念

from multiprocessing import Process

可以通過Process來構造一個子進程

p = Process(target=fun,args=(args))

再通過p.start()來啟動子進程

再通過p.join()方法來使得子進程運行結束後再執行父進程

from multiprocessing import Processimport os# 子進程要執行的代碼def run_proc(name):    print ‘Run child process %s (%s)...‘ % (name, os.getpid())if __name__==‘__main__‘:    print ‘Parent process %s.‘ % os.getpid()    p = Process(target=run_proc, args=(‘test‘,))    print ‘Process will start.‘    p.start()    p.join()    print ‘Process end.‘

  

 

在multiprocessing中使用pool

如果需要多個子進程時可以考慮使用進程池(pool)來管理

from multiprocessing import Pool

 

from multiprocessing import Poolimport os, timedef long_time_task(name):    print ‘Run task %s (%s)...‘ % (name, os.getpid())    start = time.time()    time.sleep(3)    end = time.time()    print ‘Task %s runs %0.2f seconds.‘ % (name, (end - start))if __name__==‘__main__‘:    print ‘Parent process %s.‘ % os.getpid()    p = Pool()    for i in range(5):        p.apply_async(long_time_task, args=(i,))    print ‘Waiting for all subprocesses done...‘    p.close()    p.join()    print ‘All subprocesses done.‘

  

pool建立子進程的方法與Process不同,是通過

p.apply_async(func,args=(args))實現,一個池子裡能同時啟動並執行任務是取決你電腦的cpu數量,如我的電腦現在是有4個cpu,那會子進程task0,task1,task2,task3可以同時啟動,task4則在之前的一個某個進程結束後才開始。

代碼中的p.close()是關掉進程池子,是不再向裡面添加進程了,對Pool對象調用join()方法會等待所有子進程執行完畢,調用join()之前必須先調用close(),調用close()之後就不能繼續添加新的Process了。

當時也可以是執行個體pool的時候給它定義一個進程的多少

如果上面的代碼中p=Pool(5)那麼所有的子進程就可以同時進行

多個子進程間的通訊

多個子進程間的通訊就要採用第一步中說到的Queue,比如有以下的需求,一個子進程向隊列中寫資料,另外一個進程從隊列中取資料,

 

#coding:gbkfrom multiprocessing import Process, Queueimport os, time, random# 寫資料進程執行的代碼:def write(q):    for value in [‘A‘, ‘B‘, ‘C‘]:        print ‘Put %s to queue...‘ % value        q.put(value)        time.sleep(random.random())# 讀資料進程執行的代碼:def read(q):    while True:        if not q.empty():            value = q.get(True)            print ‘Get %s from queue.‘ % value            time.sleep(random.random())        else:            breakif __name__==‘__main__‘:    # 父進程建立Queue,並傳給各個子進程:    q = Queue()    pw = Process(target=write, args=(q,))    pr = Process(target=read, args=(q,))    # 啟動子進程pw,寫入:    pw.start()        # 等待pw結束:    pw.join()    # 啟動子進程pr,讀取:    pr.start()    pr.join()    # pr進程裡是死迴圈,無法等待其結束,只能強行終止:    print    print ‘所有資料都寫入並且讀完‘

  

 

關於上面代碼的幾個有趣的問題

if __name__==‘__main__‘:        # 父進程建立Queue,並傳給各個子進程:    q = Queue()    p = Pool()    pw = p.apply_async(write,args=(q,))        pr = p.apply_async(read,args=(q,))    p.close()    p.join()       print ‘所有資料都寫入並且讀完‘

  

如果main函數寫成上面的樣本,本來我想要的是將會得到一個隊列,將其作為參數傳入進程池子裡的每個子進程,但是卻得到

RuntimeError: Queue objects should only be shared between processes through inheritance

的錯誤,查了下,大意是隊列對象不能在父進程與子處理序間通訊,這個如果想要使用進程池中使用隊列則要使用multiprocess的Manager類

if __name__==‘__main__‘:    manager = multiprocessing.Manager()    # 父進程建立Queue,並傳給各個子進程:    q = manager.Queue()    p = Pool()    pw = p.apply_async(write,args=(q,))    time.sleep(0.5)    pr = p.apply_async(read,args=(q,))    p.close()    p.join()        print    print ‘所有資料都寫入並且讀完‘

  

這樣這個隊列對象就可以在父進程與子處理序間通訊,不用池則不需要Manager,以後再擴充multiprocess中的Manager類吧

關於鎖的應用,在不同程式間如果有同時對同一個隊列操作的時候,為了避免錯誤,可以在某個函數操作隊列的時候給它加把鎖,這樣在同一個時間內則只能有一個子進程對隊列進行操作,鎖也要在manager對象中的鎖

#coding:gbkfrom multiprocessing import Process,Queue,Poolimport multiprocessingimport os, time, random# 寫資料進程執行的代碼:def write(q,lock):    lock.acquire() #加上鎖    for value in [‘A‘, ‘B‘, ‘C‘]:        print ‘Put %s to queue...‘ % value                q.put(value)            lock.release() #釋放鎖  # 讀資料進程執行的代碼:def read(q):    while True:        if not q.empty():            value = q.get(False)            print ‘Get %s from queue.‘ % value            time.sleep(random.random())        else:            breakif __name__==‘__main__‘:    manager = multiprocessing.Manager()    # 父進程建立Queue,並傳給各個子進程:    q = manager.Queue()    lock = manager.Lock() #初始化一把鎖    p = Pool()    pw = p.apply_async(write,args=(q,lock))        pr = p.apply_async(read,args=(q,))    p.close()    p.join()        print    print ‘所有資料都寫入並且讀完‘

  

python 中的multiprocessing 模組

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.