進程的基本用法:
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