multiprocessing模塊

multiprocessing模塊

因爲GIL的存在,python中的多線程其實並非真正的多線程,若是想要充分地使用多核CPU的資源,在python中大部分狀況須要使用多進程。
multiprocessing包是Python中的多進程管理包。與threading.Thread相似,它能夠利用multiprocessing.Process對象來建立一個進程。該進程能夠運行在Python程序內部編寫的函數。該Process對象與Thread對象的用法相同,也有start(), run(), join()的方法。此外multiprocessing包中也有Lock/Event/Semaphore/Condition類 (這些對象能夠像多線程那樣,經過參數傳遞給各個進程),用以同步進程,其用法與threading包中的同名類一致。因此,multiprocessing的很大一部份與threading使用同一套API,只不過換到了多進程的情境。python

#### process多線程

構造方法:

Process([group [, target [, name [, args [, kwargs]]]]])app

group:線程組,目前尚未實現,庫引用中提示必須是None;異步

target:要執行的方法async

name:進程名函數

args/kwargs:要傳入方法的參數線程

實例方法:

is_alive():返回進程是否在運行code

join([timeout]):阻塞當前上下文環境的進程程,直到調用此方法的進程終止或到達指定的timeout(可選參數)。
 
start():進程準備就緒,等待CPU調度對象

run():strat()調用run方法,若是實例進程時未制定傳入target,這star執行t默認run()方法。
 繼承

terminate():無論任務是否完成,當即中止工做進程

屬性

daemon:和線程的setDeamon功能同樣守護進程

name:進程名字。

pid:進程號。

  • Python的進程調用
from multiprocessing import Process
import time
def foo(q):
    time.sleep(1)
    print(q)

if __name__=="__main__":

    l=[]
    for i in range(3):

        p=Process(target=foo,args=("W"))
        l.append(p)
        p.start()
    for i in l:
        i.join()
    print("end")

"D:\Program Files\python.exe" E:/py_code/進程隊列/進程隊列.py
W
W
W
end

Process finished with exit code 0

上述進程的調用是比較常規的調用。

  • Proscess繼承類
from multiprocessing import Process
import time
class MyProcess(Process):
    def __init__(self):
        super(MyProcess, self).__init__()
        # self.name = name

    def run(self):

        print ('hello', self.name,time.ctime())
        time.sleep(1)


if __name__ == '__main__':
    p_list=[]
    for i in range(3):
        p = MyProcess()
        p.start()
        p_list.append(p)
    for p in p_list:
        p.join()
    print('end')


"D:\Program Files\python.exe" E:/py_code/進程隊列/進程隊列.py
hello alvin:1 Thu Jul 20 18:07:56 2017
hello alvin:0 Thu Jul 20 18:07:56 2017
hello alvin:2 Thu Jul 20 18:07:56 2017
end

Process finished with exit code 0

上面的代碼定義了一個類並繼承了一個進程,並開啓了5個進程,這5個進程會均會執行MyProcess類中的run方法即打印 ('hello',self.name,time.ctime())。

  • 進程間的通信(Queue)
from multiprocessing import Process,Queue
import queue

def foo(q):
    q.put("1")

def bar(q):

    print(q.get(),"ok")

if __name__=="__main__":
    q=Queue()  #相等於q=queue.Queue()
    for i in range(3):
        p=Process(target=foo,args=(q,))

        p1=Process(target=bar,args=(q,))
        p1.start()
        p.start()

"D:\Program Files\python.exe" E:/py_code/進程隊列/進程隊列.py
1 ok
1 ok
1 ok

Process finished with exit code 0
  • 管道(pipe)

管道()函數返回由管道鏈接的一對鏈接對象,該管道默認是雙向的(雙向的)。例如:

def foo(o):
    data=o.recv()
    print(data)
    o.send("hey!whatmini")



if __name__=="__main__":
    sock,conn=Pipe()#sock與conn至關於管道的兩個接口
#
    t1=Process(target=foo,args=(conn,))
    t1.start()
    sock.send("你好")  
    print(sock.recv())
    

"D:\Program Files\python.exe" E:/py_code/進程隊列/進程隊列.py
你好
hey!whatmini

Process finished with exit code 0

須要注意的是:Pipe()返回的兩個鏈接對象表明管道的兩端。 每一個鏈接對象都有send()和recv()方法(等等)。 請注意,若是兩個進程(或線程)嘗試同時讀取或寫入管道的同一端,管道中的數據可能會損壞

manager

Queue和pipe只是實現了數據交互,並沒實現數據共享,即一個進程去更改另外一個進程的數據。

from multiprocessing import Process, Manager

def foo(l,i):
    l.append(i*i)

if __name__ == '__main__':

    with Manager() as manager:

        manager=Manager()

        l = manager.list([11,22,33])  #建立一個列表也能夠字典類型都支持
        p_list = []
        for i in range(10):
            p = Process(target=foo, args=(l,i))
            p.start()
            p_list.append(p)

        for res in p_list:
            res.join()

        print(l)

"D:\Program Files\python.exe" E:/py_code/進程隊列/進程隊列.py
[11, 22, 33, 4, 1, 9, 36, 81, 0, 49, 16, 64, 25]

Process finished with exit code 0
進程池

進程池內部維護一個進程序列,當使用時,則去進程池中獲取一個進程,若是進程池序列中沒有可供使用的進進程,那麼程序就會等待,直到進程池中有可用進程爲止。

from multiprocessing import Pool   #
import time

def foo(args):
 time.sleep(1)
 print(args)

if __name__ == '__main__':
 p = Pool(5)   #進程池對象的最大量爲5個
 for i in range(30):  #30個任務5個進程對象去執行
     p.apply_async(func=foo, args= (i,))  #異步執行

 p.close()   # 等子進程執行完畢後關閉線程池
 # time.sleep(2)
 # p.terminate()  # 馬上關閉線程池
 p.join()  #主進程等待全部子進程執行完畢,必須在close或terminate以後

進程池內部維護一個進程序列,當使用時,去進程池中獲取一個進程,若是進程池序列中沒有可供使用的進程,那麼程序就會等待,直到進程池中有可用進程爲止。

進程池中有如下幾個主要方法:

1 apply:從進程池裏取一個進程並執行

2 apply_async:apply的異步版本

3 terminate:馬上關閉線程池

4 join:主進程等待全部子進程執行完畢,必須在close或terminate以後

6 close:等待全部進程結束後,才關閉線程池

相關文章
相關標籤/搜索