python多进程
区别于多线程:多进程是实实在在的将计算任务分配到计算机的不同的核或者说处理机上,实现进程的并行操作,能够大大提高项目的执行效率和速度
1. 创建多线程以及join()方法:语法结构与threading模块近乎相同
import multiprocessing as mp
def job(data):
p = mp.Process(target=job, args=(data,), name='p1')
p.start()
pass
if __name__ == "__main__":
p = mp.Process(target=job, args=(data,), name='p1')
p.start()
p.join()
-
mp.Process()
:创建新进程,相关参数与threading.Thread
完全相同 -
包含多进程的项目,一定要在py文件中才能运行出来,而且要求包含
if __name__ == "__main__":
,必须从主进程中创建多进程,可以有以下两种方式# Method 1: 主进程中直接调用 def fun(): pass if __name__ == "__main__": p = mp.Process(target=job, args=(data,), name='p1') p.start() # Method 2: 主进程中函数调用 def fun(): pass def mpprocess(): p = mp.Process(target=job, args=(data,), name='p1') p.start() if __name__ == "__main__": mpprocess()
2. mp.Queue():语法结构和threading近乎相同
import multiprocessing as mp
def job(data, q, pname): # q要作为参数传进来
data = list(data)*2
q.put({pname : data}) # 保存数据
if __name__ == '__main__':
q = mp.Queue() # 创建一个用于保存进程运行结果的Queue实例
p1 = mp.Process(target=job, args=(range(10), q, 'p1'))
p1.start()
p1.join() # 一定要进程完全结束
print(q.get()) # 取数据
- 在多进程
multiprocessing
中,要使用q = mp.Queue()
来创建一个队列实例
3. 进程池
这种方式用于自动优化:连续多次调用一个函数功能 或 连续多次调用不同函数功能
-
mp.Pool().map
--> 连续多次调用同一个函数,处理不同的数据import multiprocessing as mp def job(x): return data if if __name__ == '__main__': ls = [x1, x2, x3, ...] with mp.Pool() as pool: res = pool.map(job, ls) print('final')
mp.Pool()
:创建了一个进程池,默认使用计算机的所有核pool.map(job, ls)
: 这个方法的功能是将可迭代对象 ls 中的每一项依次传入执行job功能,后台会自动将每一个功能模块分配到多个核中,从而提高效率mp.pool().map
注意事项:- 上述实例中:
map
会将ls中的每一项直接传入到job函数中,就意味着ls中的每一项是什么数据类型,job函数每次收到的参数就是什么数据类型!!! - 使用进程池完成各种函数功能时,其返回值不需要使用
Queue
,pool
自动集成了数据返回功能 - 返回结果
res
的返回顺序是严格按照ls
的数据传入顺序返回的。也就是说就算部分数据的消耗时间远大于其它数据,最后的结果也是按照传入数据的顺序保存的 mp.Pool()
中指定的函数执行完毕之后才会执行后续的代码模块,相当于自备了一个join()
方法
- 上述实例中:
-
mp.Pool.map()
--> 实现连续调用多个函数,不同函数需要不同参数def fun1(x): return ... def fun2(X): return ... def fun3(x): return ... def fun(ls): f = ls[0] para = ls[1] return f[0](para) if __name__ == "__main__": ls = [[fun1, x1], [fun2, x2], [fun3, x3]] with mp.Pool() as pool: res = pool.map(fun, ls) print('final')
- 通过
fun
函数,将所有需要调用的funx
统一集中管理;将各函数和函数需要的变量使用一个列表ls
保存起来从而达成连续调用不同函数的目的 - 需要注意的是,
map
只是将可迭代对象ls
的每一项作为参数传入,所以在用于统一管理的fun
函数中,需要区分 函数部分 和 参数部分 --> 要注意函数收到的数据传入的类型
- 通过
-
mp.Pool().starmap()
def fun_starmap(a, b): print("starmap:",a+b) def fun_map(para): a = para[0] b = para[1] print("map:", a+b) if __name__ == '__main__': ls = [[1, 2], [3, 4], [5, 6]] with mp.Pool(processes=4) as pool: pool.starmap(fun_starmap, ls) with mp.Pool(processes=4) as pool: pool.map(fun_map, ls)
starmap
在处理传入的ls时的区别:map
方法并不限制ls
内部的每一项是什么样的数据结构,会直接迭代ls并将每一项传入到指定的函数中;starmap
要求ls
中的每一项都必须是可迭代对象, 而且stramap
会将每一个迭代对象拆开后传入到指定的函数中。