基于multiprocessing实现多进程并行
multiprocessing库的介绍
multiprocessing 是一个支持使用与 threading 模块类似的 API 来产生进程的包。 multiprocessing 包同时提供了本地和远程并发操作,通过使用子进程而非线程有效地绕过了 全局解释器锁。 因此,multiprocessing 模块允许程序员充分利用给定机器上的多个处理器。 它在 Unix 和 Windows 上均可运行。
multiprocessing 模块还引入了在 threading 模块中没有的API。一个主要的例子就是 Pool 对象,它提供了一种快捷的方法,赋予函数并行化处理一系列输入值的能力,可以将输入数据分配给不同进程处理(数据并行)。
场景应用
场景复现
在自动化测试过程中存在一种测试场景,需要我们重复的去执行某些操作,且这类操作存在高重复性、高独立性,但人工操作又比较耗费精力,常规的线性脚本去执行的话效率也不太高,从而想到通过多线程或者多进程去提升效率。
研究两者执行机制时发现,threading的多线程机制存在一个问题,threading多线程存在一个全局解释器锁(global interpreter lock),这表示多线程在用一时刻只会有一个线程去使用解释器,是单cpu执行多个程序的并发执行,而非并行执行。对于计算密集型任务,多线程会存在某个线程一直占用着cpu资源,其他线程一直处于等待状态,所以多线程并不适用,而多进程更适用;对于IO密集型任务,IO期间线程会释放解释器,别的线程得以使用资源,所以多线程更适于IO密集型任务。
代码实现
from multiprocessing import Pool,Manager,queues
import multiprocessing,queue,time
def fun(que,filename):
while True:
# print(que.qsize())
try:
item = que.get(block=False)
except queue.Empty:
break
print('输出数字:'+item+f',输入至文件{filename}')
def run(process_num,x,filename):
manager = multiprocessing.Manager()#多进程间建立通信
que = manager.Queue()#建立进程队列
for i in x:
que.put(i)#写入队列
pool = Pool(process_num)#创建进程池
filename_arg = [f'{filename}_{num}' for num in range(process_num)]
args = [[que,filename_arg[i]] for i in range(process_num)]#根据进程池数据量配置进程参数
pool.starmap(fun,args)#同步执行
pool.close()#关闭线程池,不再接受新的进程
pool.join()#阻塞主进程,等待子进程退出
if __name__=='__main__':
run(process_num=2,x=[f'{num}' for num in range(5)],filename='filename')