进程池的概念
开进程池是为了效率,进程直接的切换是属于IO调度,每个进程的内存空间都有自己的寄存器,堆栈和文件。那进程池是干啥? 能指定存放多少个进程,在Python中是先将这些进程创建好,当你创建了50个进程,有某一时间有任务来了,这50个进程并不是一起都去参与工作的,而是排队例如下图,进程池嗷嗷待哺的小鸡,等待着期待着任务的调度。
在这里我们要区分信号量,信号量是多个进程进行排队
这两张图我们就可以区分出,单个进程和进程池的概念。
multiprocessing模块
multiprocessing模块提供了一个process类来代表一个进程对象,这个模块表示像线程一样管理进程,这个是multiprocessing的核心,它与threading相似,对多核的CPU的利用率会比threading更好。
对于multiprocessing中的process类的构造方法如下:
_init_(self, group=None, target=None, name=None, args=(), kwargs={})
参数说明:
group:进程所属组。(一般为缺省)
target:表示调用对象。
args:表示调用对象的位置参数元组。
name:别名
kwarges:表示调用对象的字典。
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):
p = multiprocessing.Process(target=do, args=(i,))
numList.append(p)
p.start()
p.join()
print("Process end.")
运行结果:
Process-1 starting
worker 0
Process end.
Process-2 starting
worker 1
Process end.
Process-3 starting
worker 2
Process end.
Process-4 starting
worker 3
Process end.
Process-5 starting
worker 4
Process end.
Pool方法
pool是什么?pool就是我们的进程池了,让我们来看一下怎么用这个方法
进程池 : from multiprocessing import Pool
创建进程池 : Pool( numprocess , initializer , initargs )
参数 :
numprocess : 要创建的进程数,如果省略,默认使用cpu_count() + 1的值
initializer : 每个工作进程启动时要执行的可调用对象,默认为None
initargs : 是要传给initializer的参数组
import multiprocessing# 导入进程包
import os
import time # os,time这两个包的作用皆为更好的体现出我们的进程
def copy(index):
print("当前进程编号",os.getpid())
print(index)
time.sleep(1) # 打一个时间差,更容易看出其效果
if __name__ == '__main__':
pool = multiprocessing.Pool(3) # 导入进程池,括号内为最大进程数
for i in range(10):
pool.apply_async(copy,(i,))
pool.close()
pool.join()
Pool的括号内为进程池的容量,就是子进程的最大开启数量。
我们来看一下运行结果吧
是不是一目了然,池容量为3,所以进程就是三个为一组的运行
进程池的其他机制
map()
map(func, iterable[, chunksize=None])
pool类中的map方法,与内置的map函数用法基本一致,会使进程阻塞直到结束返回。
close()
关闭进程池,使其不再接受新的任务。
terminal()
结束工作进程,不再处理未处理的任务。
join()
主进程阻塞等待子进程的推出,join方法要在close或terminate之后使用。
练习:下载器
import time
from multiprocessing import Pool
def down_load(movie_name):
"""下载器"""
for i in range(5):
print("电影:{},下载进度{}%".format(movie_name,(i/4*100)))
time.sleep(1)
return movie_name
def alert(movie_name):
print("电影:{}下载完成了。。。。".format(movie_name))
if __name__=="__main__":
movie_list=["西红柿首富","功夫熊猫","囧妈","泰囧","红海行动","攀登者"]
pool = Pool(3) # 创建进程池
for movie_name in movie_list:
# 调用进程池
pool.apply_async(down_load,(movie_name,),callback=alert)
pool.close()
pool.join()
运行结果: