什么是进程
进程指的是正在进行的一个过程或者一个任务,而执行这个任务的是CPU。进程与程序的区别,可以理解为程序是我们写的一堆代码,而进程则是CPU执行这堆代码的过程,同一个程序被执行两次,就会产生两个进程。凡是硬件,都需要有操作系统进行管理,只要是操作系统,就会有进程概念,需要有创建进程的方式。进程的三种状态:
运行态:应用程序正在被CPU执行中
阻塞态:当前进程突然要做I/O操作,然后CPU去执行其他的程序
就绪态:时刻准备着能够被执行
Python 实现多进程
在Python中实现多进程有两种方式:一种是使用os模块中的fork方法,另一种是使用multiprocessing模块。两者的区别在于,fork仅适用于Unix/Linux操作系统中,对于Windows不支持,而multiprocessing则是跨平台的实现方式。
使用multiprocessing创建多进程
multiprocessing模块提供了一个Process类来描述一个进程对象(需了解面向对象编程知识点)。创建子进程时,只需要传入一个执行函数和函数的参数,就可完成一个Process实例创建,用start()方法启动进程,用join()方法进行进程间的同步。
代码语言:javascript复制import os,time
from multiprocessing import Process
#子进程要执行的函数
def proc_run(pid):
print('进程 %s (Pid:%s) 运行,进程生成时间:'%(pid,os.getpid()),time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) )
#程序入口
if __name__=='__main__':
print('当前进程ID:%s'%os.getpid())
for i in range(5):
p = Process(target=proc_run,args=(i,))
print('子进%s程启动'%i)
p.start()
p.join()
print('进程结束!')
IDE运行结果如下:
仔细观察,上面IDE窗口中打印的东西貌似没有创建的5个子进程proc_run函数中的执行内容,windows中的小坑之一,IDE输出窗口输出的主进程的内容,我们创建的进程p不是主进程,当然无输出。想要看到输出结果,要在cmd下运行python脚本,命令为:“python 脚本.py ”:
进程池运用
上面介绍了用multiprocessing中的Process类动态生成多个进程,如果要创建上百个,上千个目标,手动限制进程数量太过繁琐,这种情形下我们可以通过进程池Pool来解决。
Pool可提供指定数量的进程供用户进行调用,默认进程数是CPU的核数。当有新的请求提交到Pool中时,如果资源池还没满,就会创建一个新的进程,如果Pool中的进程数达到最大值,新的请求就会进入等待状态,直到进程池中有进程结束,才会创建新的进程来处理。
代码语言:javascript复制import os,time,random
from multiprocessing import Pool
def pool_run(pid):
print('进程 %s (Pid:%s) 运行,进程生成时间:'%(pid,os.getpid()),time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) )
time.sleep(random.random()*3)
print('进程 %s 运行结束'%id)
if __name__=='__main__':
print('当前进程ID:%s'%os.getpid())
p=Pool(processes=3)
for i in range(5):
p.apply_async(pool_run,args=(i,))
print('子进%s程启动'%i)
p.close()
p.join()
print('进程结束!')
运行结果如下:
上面的代码创建了容量为3的进程池,再向进程池中添加5个任务,从运行结果可看出,虽然是创建5个进程任务,但每次最多运行3个,当一个任务结束了,新的任务才被添加进来,而新添加的任务依然是原来的进程,从进程的pid可以看出。
注意事项:Pool对象调用join()方法会等待所有子进程执行完成,调用join()之前必须先调用close(),调用了close()方法后就不能继续添加新的Process。