1、多進程:
windows環境可以使用multiprocessing中的Process實現,該方法中有is_alive(), join(), run(), start(), terminate()方法:
Process的構造方法:
__init__(self, group=None, target=None, name=None, args=(), kwargs={})
參數說明:
2、Poolgroup:進程所屬組,基本不會用到;
target:表示調用對象
args:表示調用對象的位置參數元組
name:別名:
join()方法,和多線程類似,會阻塞主進程/主線程,直到其他進程或線程結束後,在運行主進程/線程;
[比如:當從進程/線程使用join方法後,就會提示主線程,需要等待“我”結束之後纔會繼續執行下去]
# coding=utf-8 import multiprocessing def do(n): name = multiprocessing.current_process().name print(name, 'starting') print('worker', n) return if __name__ == "__main__": numList = [] for i in range(5): p1 = multiprocessing.Process(target=do, args=(i,)) p2 = multiprocessing.Process(target=do, args=(i,)) p1.start() p2.start() p1.join() p2.join() print("Process end")
可以提供指定數量的進程供用戶調用,當有新的請求提交到Pool中,如果池還沒有滿,就會創建一個新的進程來執行請求,如果池滿,請求就會告知請先等待,直到池中有進程結束,纔會創建新的進程來執行這些請求。Pool中的主要方法:
apply()-python3之後不存在、 apply_async()、map()、close()、terminate()、join()。
apply_async() -非阻塞且支持結果返回進行回調
close() - 關閉進程池
terminate() 結束工作進程,不在處理未處理的任務
join() 主進程阻塞等待子進程的退出,join方法必須再close或terminate之後使用。
import time from multiprocessing import Pool def run(f): time.sleep(1) return f * f if __name__ == "__main__": testFL = [1, 2, 3, 4, 5] print("order to run") s = time.time() for f in testFL: run(f) e1 = time.time() print("order to run"), int(e1 - s) print("concurrent") pool = Pool(2) r1 = pool.map(run, testFL) pool.close() pool.join() e2 = time.time() print("run time", int(e2 - e1)) print(r1)
3、進程間通信-Queue
from multiprocessing import Process, Queue def func(qq): qq.put("hello, Process") if __name__ == "__main__": q = Queue() p = Process(target=func, args=(q,)) p.start() print(q.get()) print(q.get_nowait()) p.join()
Queue中常用的方法:
- Queue.qsize() #獲取隊列的大小
- Queue.empty() #判斷隊列是否爲空, 空返回True,否則返回False
- Queue.full() #判斷隊列是否滿,滿返回True,否則返回False
- Queue.get([block,[timeout]]) #獲取隊列內容,如果隊列爲空,則阻塞
- Queue.get_nowait() #與get()方法類似,不過如果隊列爲空,不等待,拋出空異常
- Queue.put(item) #將item寫入隊列中,如果隊列已滿,則阻塞
- Queue.put_nowait(item) #寫入隊列,如果隊列已滿,拋出異常(如果通過循環添加隊列,循環大小超出隊列大小,則一個item也添加不成功)
- q = Queue(size) # 設置Queue的大小
除了基本的FIFO 隊列外,還提供LIFO 隊列[原則爲後進先出],Priority Queue,存儲元素時,使用優先級設置item在隊列中的順序【q.put(priority, item)】。
4、進程間通信-PIPE
from multiprocessing import Process, Pipe def func(conn): conn.send("hello, parent !") conn.send("I'm ready!") print("parent answer:", conn.recv()) conn.close() if __name__ == "__main__": par_conn, child_conn = Pipe() p = Process(target=func, args=(child_conn,)) p.start() print("child message", par_conn.recv()) print("parent answer:", par_conn.send("hello son !")) p.join()
5、進程間通信manager、
其中,managers子模塊支持把多進程分佈到多臺機器上,一個服務器進程作爲調用者,多個客戶端連接到服務器進程,執行多進程任務。
# job類 class Job: def __init__(self, job_id): self.job_id = job_id
#進程服務器 from multiprocessing import Queue from multiprocessing.managers import BaseManager from job import Job class Master: def __init__(self): self.dispatched_job_queue = Queue() self.finished_job_queue = Queue() def get_dispatch_job_queue(self): return self.dispatched_job_queue def get_finished_job_queue(self): return self.finished_job_queue def start(self): BaseManager.register('get_dispatched_job_queue', callable=self.get_dispatch_job_queue) BaseManager.register('get_finished_job_queue', callable=self.get_finished_job_queue) key = "jobs".encode() manager = BaseManager(address=('127.0.0.1', 9988), authkey=key) manager.start() dispatched_jobs = manager.get_dispatched_job_queue() finished_jobs = manager.get_finished_job_queue() job_id = 0 while True: for i in range(0, 10): job_id = job_id + 1 job = Job(job_id) print('Dispatch job: %s' % job.job_id) dispatched_jobs.put(job) while not dispatched_jobs.empty(): job = finished_jobs.get(60) print('Finished job: %s' % job.job_id) manager.shutdown() if __name__ == "__main__": master = Master() master.start()
# 客戶端進程 # coding: utf-8 from multiprocessing import Queue from multiprocessing.managers import BaseManager from job import Job import time class Slave: def __init__(self): self.dispatched_job_queue = Queue() self.finished_job_queue = Queue() def start(self): BaseManager.register('get_dispatched_job_queue') BaseManager.register('get_finished_job_queue') server = '127.0.0.1' key = 'jobs'.encode() print("Connect to server %s... " % server) manager = BaseManager(address=(server, 9988), authkey=key) manager.connect() dispatched_jobs = manager.get_dispatched_job_queue() finished_jobs = manager.get_finished_job_queue() while True: job = dispatched_jobs.get(timeout = 1) print('Run job: %s' % job.job_id) time.sleep(1) finished_jobs.put(job) if __name__ == "__main__": slave = Slave() slave.start()