程序不能單獨執行,只有將程序裝載到內存中,系統爲它分配資源才能運行,而這種執行的過程就叫作進程。進程是操做系統調度的最小單位。app
程序和進程的區別在於:程序是儲存在硬盤上指令的有序集合,是靜態的;進程是內存中程序的一次執行過程,屬於動態概念。async
進程是資源的集合,進程要在CPU執行,必需要建立線程,至少要有一個線程在運行。ide
1.線程共享建立它的進程的地址空間。進程的內存空間是獨立的。函數
2.線程能夠直接訪問其進程的數據段(不一樣線程共享同一個進程的數據),進程間不共享。ui
3.線程能夠與其餘線程進行通訊,進程必須使用進程間通訊(中間代理)與同級進程進行通訊。spa
4.新的線程很容易建立,新的進程須要父進克隆。操作系統
5.線程能夠直接操做和控制同一進程內的其它線程,而進程只能操做子進程。線程
6.對主線程的修改可能會影響到其它線程的行爲。對父進程的修改不會影響子進程(不刪除父進程的前提下)。3d
Process 類用來描述一個進程對象。建立子進程的時候,只須要傳入一個執行函數和函數的參數便可完成 Process 示例的建立。代理
star() 方法啓動進程。
join() 方法實現進程間的同步,等待全部進程退出。
close() 用來阻止多餘的進程涌入進程池 Pool 形成進程阻塞。
multiprocessing.Process(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)
target 是函數名字,須要調用的函數
args 函數須要的參數,以 元組 的形式傳入
multiprocessing模塊的使用跟線程相似
import multiprocessing import threading import time def t_run(): print("線程號",threading.get_ident()) # 線程id
def run(name): time.sleep(1) print('hello', name) t = threading.Thread(target=t_run) t.start() if __name__ == '__main__': for i in range(10): p = multiprocessing.Process(target=run, args=(i,)) p.start()
全部的進程都是由父進程啓動的,因此發現此程序的父進程ID正是PyCharm。
每一個進程都是相互獨立的,存在於不一樣的內存地址。
進程隊列直接使用multiprocessing模塊的Queue類,不一樣於線程隊列的queue模塊。
import multiprocessing def f(q): q.put([42, None, 'hello']) q.put(30) if __name__ == '__main__': q = multiprocessing.Queue() p = multiprocessing.Process(target=f, args=(q,)) # 將隊列copy一份傳給子進程
p.start() print(q.get()) # 在父進程中取出隊列中數據
print(type(q.get())) p.join()
兩個進程在管道兩邊收發數據。
import multiprocessing '''Pipe管道實例,兩個進程在管道兩邊收發數據'''
def f(conn): conn.send([42, None, 'hello']) # 發送數據
print("child_conn接收:",conn.recv()) # 接收數據
conn.close() def s(conn): conn.send("你好,紫禁城") # 發送數據
print("parent_conn接收:",conn.recv()) # 接收數據
conn.close() if __name__ == '__main__': parent_conn, child_conn = multiprocessing.Pipe() # 管道實例,鏈接着兩個進程
p = multiprocessing.Process(target=f, args=(child_conn,)) p2 = multiprocessing.Process(target=s,args=(parent_conn,)) p.start() p2.start() #print(parent_conn.recv()) # 父進程接收管道的數據
#parent_conn.send("你好,紫禁城") # 父進程發送數據
p.join() p2.join()
使用Manger()能夠建立共享的數據,包括列表,字典,元組等多種類型。
from multiprocessing import Process, Manager def f(d, l): d[1] = '1' d['2'] = 2 d[0.25] = None l.append(1) print(l) if __name__ == '__main__': with Manager() as manager: d = manager.dict() l = manager.list(range(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)
屏幕鎖,防止一個進程未打印完畢,另外一個進程插入
def f(l,i): l.acquire() print("hello",i) l.release() if __name__ == '__main__': l=Lock() for i in range(10): Process(target=f,args=(l,i)).start()
在利用Python進行系統管理的時候,特別是同時操做多個文件目錄,或者遠程控制多臺主機,並行操做能夠節約大量的時間。當被操做對象數目不大時,能夠直接利用multiprocessing中的Process動態成生多個進程,10幾個還好,但若是是上百個,上千個目標,手動的去限制進程數量卻又太過繁瑣,這時候進程池Pool發揮做用的時候就到了。
Pool能夠提供指定數量的進程,供用戶調用,當有新的請求提交到pool中時,若是池尚未滿,那麼就會建立一個新的進程用來執行該請求;但若是池中的進程數已經達到規定最大值,那麼該請求就會等待,直到池中有進程結束,纔會建立新的進程來它。這裏有一個簡單的例子:
from multiprocessing import Process, Pool import time, os def Foo(i): time.sleep(5) print('in process[Foo]', os.getpid()) return i + 100
def Bar(arg): # 父進程去執行,而不是子進程調用
print('-->exec done:', arg) print('in process[Bar]', os.getpid()) if __name__ == '__main__': pool = Pool(5) # 容許進程池裏同時放入5個進程 其餘多餘的進程處於掛起狀態
for i in range(10): pool.apply_async(func=Foo, args=(i,), callback=Bar) # pool.apply(func=Foo, args=(i,))
print('end:', os.getpid()) pool.close() # close() 必須在join()前被調用
pool.join() # 進程池中進程執行完畢後再關閉,若是註釋,那麼程序直接關閉。