標籤:python 多進程
multiprocessing在python2.6+版本中得到應用。
multi意思為多個,processing意思為進程 也就是實現多進程。可以實現利用調用電腦的多個CPU實現多線程。
multiprocessing是一個包,支援使用類似threading模組的API產生進程。multiprocessing包提供本地和遠程兩種並發,通過使用子進程而非線程有效地迴避了全域解譯器鎖。 因此,multiprocessing模組允許程式員充分利用一個給定機器的多個處理器。它在Unix和Windows上都可允許。
下面主要介紹進程類:
線程是通過建立Process對象,然後調用start()方法來產生的。Process繼承了threading.Thread的API。現在舉一個multiprocess 的例子:
使用Process建立進程:
from multiprocessing import Processdef f(name): print ‘hello‘, nameif __name__ == ‘__main__‘: p = Process(target=f, args=(‘bob‘,)) #建立一個線程 p.start() #調用start方法 啟動 p.join()
下面是一個活的線程ID的例子:
from multiprocessing import Processimport osdef info(title): print title print ‘module name:‘, __name__ if hasattr(os, ‘getppid‘): # 只在Unix中可使用 print ‘parent process:‘, os.getppid() print ‘process id:‘, os.getpid()def f(name): info(‘function f‘) print ‘hello‘, nameif __name__ == ‘__main__‘: info(‘main line‘) p = Process(target=f, args=(‘bob‘,)) p.start() p.join()
代碼中使用os的getpid()獲得父進程的ID 使用getip()獲得當前進程的ID,另外還可以使用getppid獲得父進程的父進程的ID。
IPC(Inter-Process Communication) 進程間的通訊
multiprocessing包中有Pipe類和Queue類來分別支援這兩種IPC機制。Pipe和Queue可以用來傳送常見的對象。
Pipe可以是單向(half-duplex),也可以是雙向(duplex)。我們通過mutiprocessing.Pipe(duplex=False)建立單向管道 (預設為雙向)。一個進程從PIPE一端輸入對象,然後被PIPE另一端的進程接收,單向管道只允許管道一端的進程輸入,而雙向管道則允許從兩端輸入。
舉例:(單向的)
from multiprocessing import Process, Pipedef f(conn): #conn為父線程傳遞過來的pipe對象 conn.send([42, None, ‘hello‘]) #在pipe對象的一端發送資料 conn.close() #關閉if __name__ == ‘__main__‘: parent_conn, child_conn = Pipe() #定義兩個Pipe對象來建立 p = Process(target=f, args=(child_conn,))#建立一個進程 傳遞的參數為pipe對象 p.start() print parent_conn.recv() # prints "[42, None, ‘hello‘]" #在父進程中使用另一個pipe對象的recv()方法接受資料 p.join()
每個連線物件都有send和recv方法,需要注意的是,如果兩個進程或者線程同時讀取或寫入pipe對象的終端,則可能引起終端。如果同時使用pipe的不同終端則不會有風險。
下面舉例:(雙向)
import multiprocessing as muldef proc1(pipe): pipe.send(‘hello‘) print(‘proc1 rec:‘,pipe.recv())def proc2(pipe): print(‘proc2 rec:‘,pipe.recv()) pipe.send(‘hello, too‘)if __name__ == ‘__main__‘: mul.freeze_support() pipe1,pipe2= mul.Pipe() #建立兩個pipe對象 # Pass an end of the pipe to process 1 p1 = mul.Process(target=proc1, args=(pipe1,)) #建立p1線程 # Pass the other end of the pipe to process 2 p2 = mul.Process(target=proc2, args=(pipe2,)) #建立p2線程 p1.start() #調用線程1 p2.start() #調用線程2 p1.join() #這裡等待線程1執行完成 p2.join() #等待線程2執行完成#輸出:(‘proc2 rec:‘, ‘hello‘)(‘proc1 rec:‘, ‘hello, too‘)
這個例子實現了兩個線程之間的通訊,實現了雙向通訊。線程1: proc1中發送”hello”字串,線程proc2中接收線程1proc1中發送的”hello”字串並輸出,然後proc2發送”hello, too”字串,線程1 proc1接收到proc2發送的字串並輸出。
下面介紹另外一種實現IPC的方式:
Queue:
Queue與Pipe相類似,都是先進先出的結構。但Queue允許多個進程放入,多個進程從隊列取出對象。Queue使用mutiprocessing.Queue(maxsize)建立,maxsize表示隊列中可以存放對象的最大數量。
下面的程式展示了Queue的使用:
from multiprocessing import Process, Queuedef f(q): q.put([42, None, ‘hello‘]) #調用主函數中p進程傳遞過來的進程參數 put函數為向隊列中添加一條資料。if __name__ == ‘__main__‘: q = Queue() #建立一個Queue對象 p = Process(target=f, args=(q,)) #建立一個進程 p.start() print q.get() # prints "[42, None, ‘hello‘]" p.join()
上面是一個queue的簡單應用,使用隊列q對象調用get函數來取得隊列中最先進入的資料。
舉一個複雜些的例子:
import multiprocessingimport time# 向queue中輸入資料的函數def inputQ(queue): info = str(os.getpid()) + ‘(put):‘ + str(time.time()) queue.put(info)# 向queue中輸出資料的函數def outputQ(queue,lock): info = queue.get() lock.acquire() print (str(os.getpid()) + ‘(get):‘ + info) lock.release()# Mainif __name__ == ‘__main__‘: multiprocessing.freeze_support() record1 = [] # store input processes record2 = [] # store output processes lock = multiprocessing.Lock() #使用鎖方法輸出錯亂 queue = multiprocessing.Queue(3) # 輸入進程 for i in range(10): process = multiprocessing.Process(target=inputQ,args=(queue,)) process.start() record1.append(process) # 輸出進程 for i in range(10): process = multiprocessing.Process(target=outputQ,args=(queue,lock)) process.start() record2.append(process) for p in record1: p.join() queue.close() # 如果沒有資料進入隊列中則關閉隊列 for p in record2: p.join()#輸出結果為:15212(get):7180(put):1440649672.228820(get):7020(put):1440649672.856164(get):7872(put):1440649673.3910904(get):9436(put):1440649673.685016(get):16840(put):1440649674.0712004(get):12848(put):1440649674.3814456(get):11608(put):1440649674.662468(get):16884(put):1440649674.856464(get):8944(put):1440649674.897576(get):15476(put):1440649674.92
這個例子中,建立了二十個進程,十個是用來寫入隊列資料的,另外十個是用來輸出隊列中的資料的。
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
multiprocessing 基於進程的“線程式”介面 python