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()