多進程
- 啟用多進程,可以解決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() # 進程池中進程執行完畢后再關閉,如果注釋,那么程序直接關閉。