Python进程池
当需要创建的子进程数量不多时,可以直接利用multiprocessing中的Process动态成生多个进程,但如果是上百甚至上千个目标,手动的去创建进程的工作量巨大,此时就可以用到multiprocessing模块提供的Pool方法。
初始化Pool时,可以指定一个最大进程数,当有新的请求提交到Pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到指定的最大值,那么该请求就会等待,直到池中有进程结束,才会用之前的进程来执行新的任务。
导入
import multiprocessing
import time
import os
import random
封装一个逻辑函数
def test1(msg):
t_start = time.time()
print("%s开始执行,进程号为%d" % (msg, os.getpid()))
time.sleep(random.random() * 2)
t_stop = time.time()
print("%s执行完成,耗时%.2f" % (msg, t_stop - t_start))
编写主函数
if __name__ == "__main__":
po = multiprocessing.Pool(3) #同时创建三个进程
for i in range(0, 10):
# Pool().apply_async(要调用的目标,(传递给目标的参数元祖,))
# 每次循环将会用空闲出来的子进程去调用目标
po.apply_async(test1, (i,))
print("-----start-----")
po.close() # 关闭进程池,关闭后po不再接收新的请求
po.join() # 等待po中所有子进程执行完成,必须放在close语句之后
print("-----end-----")
运行结果
-----start-----
0开始执行,进程号为40291
1开始执行,进程号为40292
2开始执行,进程号为40293
2执行完成,耗时0.59
3开始执行,进程号为40293
0执行完成,耗时1.21
4开始执行,进程号为40291
1执行完成,耗时1.56
5开始执行,进程号为40292
3执行完成,耗时1.58
6开始执行,进程号为40293
5执行完成,耗时1.36
7开始执行,进程号为40292
4执行完成,耗时1.73
8开始执行,进程号为40291
6执行完成,耗时1.34
9开始执行,进程号为40293
8执行完成,耗时0.71
9执行完成,耗时0.36
7执行完成,耗时1.21
-----end-----
参数
1、apply()
函数原型:apply(func[, args=()[, kwds={}]])
该函数用于传递不定参数,同python中的apply函数一致,主进程会被阻塞直到函数执行结束(不建议使用,并且3.x以后不在出现)。
2、apply_async
函数原型:apply_async(func[, args=()[, kwds={}[, callback=None]]])
与apply用法一致,但它是非阻塞的且支持结果返回后进行回调。
3、map()
函数原型:map(func, iterable[, chunksize=None])
Pool类中的map方法,与内置的map函数用法行为基本一致,它会使进程阻塞直到结果返回。
注意:虽然第二个参数是一个迭代器,但在实际使用中,必须在整个队列都就绪后,程序才会运行子进程。
4、map_async()
函数原型:map_async(func, iterable[, chunksize[, callback]])
与map用法一致,但是它是非阻塞的。其有关事项见apply_async。
5、close()
关闭进程池(pool),使其不在接受新的任务。
6、terminal()
结束工作进程,不在处理未处理的任务。
7、join()
主进程阻塞等待子进程的退出, join方法要在close或terminate之后使用。