Python-多进程
一、多进程
from multiprocessing import Process import os def func1(num): print(num) if __name__ == '__main__': print('主进程id为:', os.getpid()) #获取主进程id for i in range(10): p = Process(target=func1,args=(i,)) #创建子进程 p.start() #调起子进程 print('子进程名称为:', p.name) #获取子进程名称 print('子进程id为', p.pid) #获取子进程id
二、同时运行多进程时,每个进程默认都拥有一份独立的数据;通过全局变量并不能实现进程间的数据通信
a = 1 def func2(): global a a +=1 print('子进程中的a:', a) #子进程中的a: 2 if __name__ == '__main__': p = Process(target=func2) p.start() p.join() print('主进程中的a:', a) #主进程中的a: 1
三、进程间数据通信
1、借助Queue、pipe等进行通信
from multiprocessing import Process, Queue import os, time, random def write_queue(q): #写数据到队列 for value in range(10): print('Put %s to queue...'%value) q.put(value) time.sleep(2) #每隔2秒写入数据 def read_queue(q): #从队列读取数据 while True: value = q.get(True) print('Get %s from queue.' %value) time.sleep(3) #每隔3秒读取数据 if q.empty(): #若队列为空,退出循环 print('队列为空,请输入数据后再读') break if __name__=='__main__': q = Queue() #父进程创建Queue,传给子进程 pw = Process(target=write_queue, args=(q,)) pr = Process(target=read_queue, args=(q,)) start = time.time() pw.start() #启动子进程pw,写数据 pr.start() #启动子进程pr,读数据 pw.join() end_pw = time.time() run_pw = end_pw - start #计算写数据的时间 pr.join() #terminate()可强行终止进程 end_pr = time.time() run_pr = end_pr - start #计算读数据的时间 print('写数据花费时间:', run_pw, '读数据花费时间', run_pr)
2、借助Manager实现进程间的数据通信;Manager支持的类型非常多,包括: Value,Array,list, dict,Queue, Namespace, Lock, RLock, Semaphore, BoundedSemaphore, Condition, Event等
from multiprocessing import Process, Manager import time def func(p_dict, p_list): #入参:p_dict为字典,p_list为list for i in range(10): time.sleep(2) k = str(i) + '*' + str(i) p_dict[k] = i * i for i in range(10): time.sleep(1) p_list.append(i) if __name__ == "__main__": manager = Manager() dt = manager.dict() #创建dict实例 lt = manager.list() #创建list实例 start = time.time() p = Process(target=func, args=(dt, lt)) p.start() p.join() end = time.time() run_time = end - start print(dt, '\n', lt) print('运行时间为:',run_time) #运行时间大约为30s
四、进程池
1、通过apply_async()可批量创建子进程
2、从进程池获取进程时,先判断进程池是否已满;若进程池满了,则需要等待进程池重新有空余的进程(池中其他被调用的子进程结束),再继续
from multiprocessing import Pool import time def func2(num): time.sleep(2) print(num) if __name__ == '__main__': start = time.time() pool = Pool(5) #创建进程池,最多可同时运行5个子进程 for i in range(5): pool.apply_async(func=func2,args=(i,)) #apply_async()调用子进程 print('执行主程序') pool.close() pool.join() #等待子进程结束再结束主进程 end = time.time() run_time = end - start print(run_time)
run_time的时间取决于进程池的个数pool = Pool(N):
1)当N=2时,每次只能从进程池取2个子进程,5个子进程要分三次调用:run_time = 2 + 2 + 2
2)当N=3时,每次只能从进城池取3个子进程,5个子进程要分2次调用:run_time = 2 + 2
3)当N>=5时,可同时调用5个子进程:run_time = 2