進程、多進程、進程間數據交互、進程同步、進程池


多進程

  • 啟用多進程,可以解決python調用計算機CPU多核運算的問題

啟動一個進程

import multiprocessing
import time

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

for i in range(10):
    p = multiprocessing.Process(target=run,args=('man %s'%i,))
    p.start()

from multiprocessing import Process
import os

def info(title):
    print(title)
    print('module name:', __name__)
    print('parent process:', os.getppid())#父進程ID
    print('process id:', os.getpid())#當前進程ID
    print("\n\n")

def f(name):
    info('\033[31;1mfunction f\033[0m')#子進程的info,子進程的PPID=主進程的PID
    print('hello', name)

if __name__ == '__main__':
    info('\033[32;1mmain process line\033[0m')#主進程的info
#在window,主進程的PPID=pycharm的PID
    p = Process(target=f, args=('bob',))
    p.start()
    p.join()
  • 每一個進程都是由一個父進程啟動的

進程間數據交互

  • 不管哪種方式,都是找一個中間代理,相當於不同國家的人交流需要找一個翻譯
  • 不同進程間內存是不共享的,要想實現兩個進程間的數據交換,可以用以下方法:

進程間數據交互(通信)的方式

1.Queues

  • 使用方法跟threading里的queue差不多。這里的queue不是線程中的,線程中的queue只能在創建線程的主進程之間由它的線程使用
from multiprocessing import Process, Queue
#用法和線程的queue是一樣的,但這里引入的是進程的queue
def f(q):
    q.put([42, None, 'hello'])

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

2.Pipes管道

  • 管道實例化后會產生兩個通道,分別交給兩個進程
  • 通過send和recv來交互數據,這是一個雙向的管道,child和parent可以互相收發
from multiprocessing import Process, Pipe

def f(conn):
    conn.send([42, None, 'hello'])
    conn.close()

if __name__ == '__main__':
    parent_conn, child_conn = Pipe()
    p = Process(target=f, args=(child_conn,))
    p.start()
    print(parent_conn.recv())  # prints "[42, None, 'hello']"
    p.join()

3.Managers經理/代理

  • 以代理的方式在進程間共享字典或列表形式的數據
from multiprocessing import Process, Manager
import os
def f(d, l):
    d[1] = '1'
    d['2'] = 2
    d[0.25] = None
    l.append(os.getpid())
    print(l)

if __name__ == '__main__':
    with Manager() as manager:
        d = manager.dict()#生成一個字典,在多個進程間共享和傳遞

        l = manager.list(range(5))#生成一個列表含5個初始值,在多個進程間傳遞和共享
        p_list = []
        for i in range(10):
            p = Process(target=f, args=(d, l))
            p.start()
            p_list.append(p)
        for res in p_list:
            res.join()

        print(d)
        print(l)

進程同步LOCK

  • 進程不能操作同一塊數據,那么進程鎖的意義是什么?
  • 進程鎖存在的意義是保證各進程在屏幕輸出時不會亂
    比如:進程1,打印hello word 1,進程2打印hello word 2,沒有鎖,進程1的打印還沒結束,進程2進來了,就可能造成混亂。(window上不會發生,linux上測試,2.7以下python)
from multiprocessing import Process, Lock

def f(l, i):
    l.acquire()
    try:
        print('hello world', i)
    finally:
        l.release()

if __name__ == '__main__':
    lock = Lock()

    for num in range(10):
        Process(target=f, args=(lock, num)).start()

進程池

  • 進程池內部維護一個進程序列,當使用時,則去進程池中獲取一個進程,如果進程池序列中沒有可供使用的進進程,那么程序就會等待,直到進程池中有可用進程為止。
  • 進程池中有兩個方法:
  • apply同步執行-串行
  • apply_async異步執行-並行
from  multiprocessing import Process, Pool
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__':
    pool = Pool(5)#同時允許5個進程進入進程池,其他進程掛起

    for i in range(10):
        pool.apply_async(func=Foo, args=(i,), callback=Bar)#callback回調函數
        # pool.apply(func=Foo, args=(i,))

    print('end')
    pool.close()#這里join一定是在close之后,且必須要加join,否則主進程不等待創建的子進程執行完畢
    pool.join()  # 進程池中進程執行完畢后再關閉,如果注釋,那么程序直接關閉。

from concurrent.futures import ThreadPoolExecutor線程池必用模塊

from concurrent.futures import ProcessPoolExecutor進程池必用模塊

參考文檔


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM