Python3 進程multiprocessing的基本用法

進程的基本用法: 

multiprocessing是一個使用類似於線程模塊的API支持產生進程的包。 多處理包提供本地和遠程併發,通過使用子進程而不是線程有效地側向執行全局解釋器鎖。 因此,多處理模塊允許程序員充分利用給定機器上的多個處理器。 它可以在Unix和Windows上運行。

import multiprocessing
import time


def f(name):
    time.sleep(2)
    print('hello', name)


if __name__ == '__main__':
    p = multiprocessing.Process(target=f, args=('bob',))
    p.start()
    p.join()

進程間的通信:

不同進程由於內存不是共享的,如果想要實現不同進程之間的數據交換,可以用以下方法:

Queues:

使用的方式和threading裏得queue差不多,需要注意的是:這裏的Queue是進程裏得隊列,而不是線程裏面的

from multiprocessing import Process, Queue
# import queue  這是進程裏面的queue

def f(q):
    q.put([42, None, 'hello'])
if __name__ == '__main__':
    q = Queue()
    # q.put([42, None, 'hello'])
    p = Process(target=f,args=(q,))
    p.start()
    print(q.get())  # prints "[42, None, 'hello']"
    p.join()
運行結果:
[42, None, 'hello']

Pipes:

Pipe()函數返回一個由管道連接的連接對象,默認情況下是雙工(雙向)。

from multiprocessing import Process, Pipe


def f(conn):
    conn.send("發送給parent")
    print("child receive:", conn.recv())
    conn.close()


if __name__ == '__main__':
    parent_conn, child_conn = Pipe() # 創建父管道和子管道
    p = Process(target=f, args=(child_conn,))
    p.start()
    print("parent receive:",parent_conn.recv())
    parent_conn.send("發送給child")
    parent_conn.close()
    p.join()
運行結果:
parent receive: 發送給parent
child receive: 發送給child

Manages:

Manager()返回的管理器對象控制一個服務器進程,該進程保存Python對象並允許其他進程使用代理操作它們。Manager()返回的管理器將支持類型列表,dict,Namespace,Lock,RLock,Semaphore,BoundedSemaphore,Condition,Event,Barrier,Queue,Value和Array。 例如:

from multiprocessing import Process, Manager
import os

def f(d, l):
    d[1] = 'Python'
    d[2] = "Java"
    d[3] = "C++"
    l.append(os.getpid()) # 在I中添加進程號,os.getpid()獲得當前的進程號
    print(l)


if __name__ == '__main__':
    with Manager() as manager:
        d = manager.dict() # 創建一個字典
        l = manager.list(range(5)) # 創建一個列表
        p_list = [] # 創建一個空列表存放進程
        for i in range(3):
            p = Process(target=f, args=(d, l))
            p.start()
            p_list.append(p)
        for res in p_list:
            res.join()
        print(d)
        print(l)
運行結果:
[0, 1, 2, 3, 4, 47940]
[0, 1, 2, 3, 4, 47940, 23300]
[0, 1, 2, 3, 4, 47940, 23300, 19108]
{1: 'Python', 2: 'Java', 3: 'C++'}
[0, 1, 2, 3, 4, 47940, 23300, 19108]

進程同步:

通過進程鎖開啓多個進程,用法和線程鎖相似。

from multiprocessing import Process, Lock
import os
def f(l, i):
    l.acquire()  # 獲得進程鎖
    try:
        print('Running process:', i, os.getpid())
    finally:
        l.release() # 釋放進程鎖

if __name__ == '__main__':
    lock = Lock() # 實例化一個進程鎖
    for num in range(3):
        Process(target=f, args=(lock, num)).start()
運行結果:
Running process: 0 51016
Running process: 1 43240
Running process: 2 50932

進程池:

進程池內部維護一個進程序列,當使用時,則去進程池中獲取一個進程,如果進程池序列中沒有可供使用的進程,那麼程序就會等待,直到進程池中有可用進程爲止,與線程裏面的信息量相似。進程池中有兩個方法:

  • apply
  • apply_async
from multiprocessing import Process, Pool,freeze_support
import time, os


def Foo(i):
    time.sleep(2)
    print("in process:", os.getpid())
    return i + 100


def Bar(arg):
    print('-->exec done:', arg)


if __name__ == '__main__':

    # freeze_support()
    print("dsd")
    pool = Pool(5) # 允許進程池裏同時放入5個進程

    for i in range(10):
         pool.apply_async(func=Foo, args=(i,), callback=Bar) # 並行,callback=回調,執行完func之後,再回來執行callback
         # pool.apply(func=Foo, args=(i,)) # 進程串行

    print('end')
    pool.close()
    pool.join()  # 進程池中進程執行完畢後再關閉,如果註釋,那麼程序直接關閉。

#apply_async運行結果:
dsd
end
in process: 49788
-->exec done: 100
in process: 48364
-->exec done: 101
in process: 49964
-->exec done: 102
in process: 48048
-->exec done: 103
in process: 49580
-->exec done: 104
in process: 49788
-->exec done: 105
in process: 48364
-->exec done: 106
in process: 49964
-->exec done: 107
in process: 48048
-->exec done: 108
in process: 49580
-->exec done: 109
#apply運行結果:
dsd
in process: 3988
in process: 48940
in process: 48268
in process: 20156
in process: 42952
in process: 3988
in process: 48940
in process: 48268
in process: 20156
in process: 42952
end

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章