多进程
概念:
程序:例如xxx.py是一个程序,他是静态的,没有运行起来。
进程:当一个程序运行了起来,代码+所用到的资源称之为进程。进程是操作系统分配资源的最小单位。
线程:线程是一个程序里的一条执行路线,线程是程序执行的最小单位。
进程的状态:
如果任务数大于cpu数量,会有一部分程序在被cpu执行,一部分在等待执行,就有了不同的进程状态
- 就绪态:运行的条件都已满足,正在等待cpu执行
- 执行态:cpu正在执行其功能
- 等待态:等待某些条件满足,例如sleep,程序就会处在等待态(堵塞)
multiprocessing:
由于GIL全局解释器锁的存在,python中的多线程并不是真的多线程,如果需要充分使用cpu资源需要使用多进程。
Python提供了非常好用的多进程包multiprocessing,只需要定义一个函数,Python会完成其他所有事情。
Process:
Process的语法结构:
Process([group [,target [,name [,args [,kwargs]]]]])
- group:指定进程组,基本不用
- target:如果传入了函数的引用,可以让这个子进程就执行这个函数的代码
- args:给传入的函数传递参数,以元组形式传递(元组)
- kwargs:给传入的函数传递默认字参数(字典)
- name:给进程设定一个名字,可以不设定
Process 实例对象的常用方法
- start() 启动一个子进程(创建子进程)
- is_alive() 查看一个子进程是否还活着
- join([timeout]) 是否等待至今从执行结束,或者等待多少秒
- terminate() 立即结束一个子进程
Process创建的实例对象的常用属性:
- name:当前进程的别名,进程名为 Process-N ,N为从1开始递增的整数
- pid:当前进程的进程号
创建进程的两种方式:
- 手动创建
- 进程池
手动创建
- import multiprocessing 导入multiprocessing包
- 对象名 = Process(target=函数名) 创建Process类的对象,创建进程
- 对象名.start() 启动进程
注:由于代码执行过快,为了显示效果,使用sleep延时执行。
代码:
from multiprocessing import Process
import os
import time
def run_pro(num):
"""子进程执行的代码"""
for i in range(num):
print("子进程执行中--%d--pid=%s" % (i, os.getpid()))
time.sleep(0.5)
def main():
m = Process(target=run_pro, args=(5, ))
m.start()
for i in range(5):
print("主进程执行中--%d--pid=%s" % (i, os.getpid()))
time.sleep(0.5)
if __name__ == '__main__':
main()
执行结果:
主进程执行中--0--pid=10724
子进程执行中--0--pid=13748
主进程执行中--1--pid=10724
子进程执行中--1--pid=13748
主进程执行中--2--pid=10724
子进程执行中--2--pid=13748
主进程执行中--3--pid=10724
子进程执行中--3--pid=13748
主进程执行中--4--pid=10724
子进程执行中--4--pid=13748
进程池Pool:
当只需要几个进程的时候,可以用multiprocessing的Process类手动创建,但是当需要成百上千个目标的时候,手动创建工作量巨大,可以用multiprocessing的Pool方法。
初始化Pool时,可以指定一个最大进程数,当有新的请求提交到Pool中时,如果池还没有满,那么就会创建一个新的进程用来执行该请求;但如果池中的进程数已经达到指定的最大值,那么该请求就会等待,直到池中有进程结束,才会用之前的进程来执行新的任务。
代码:
注:由于代码执行过快,为了显示效果,使用sleep延时执行。
import multiprocessing
import os
import time
def pro_pool(name):
"""进程池进程执行代码"""
for i in range(3):
print("进程%d执行中--%d--,pid=%d" % (name, i, os.getpid()))
time.sleep(0.5)
def main():
pool = multiprocessing.Pool(3)
for i in range(6):
pool.apply_async(pro_pool, (i, ))
pool.close() # 关闭进程池不再接受新的请求
pool.join() # 等待所有进程执行完毕
if __name__ == '__main__':
main()
执行结果(同时只有三个进程在执行):
进程0执行中--0--,pid=1740
进程1执行中--0--,pid=12232
进程2执行中--0--,pid=11420
进程0执行中--1--,pid=1740
进程1执行中--1--,pid=12232
进程2执行中--1--,pid=11420
进程0执行中--2--,pid=1740
进程1执行中--2--,pid=12232
进程2执行中--2--,pid=11420
进程3执行中--0--,pid=1740
进程4执行中--0--,pid=12232
进程5执行中--0--,pid=11420
进程3执行中--1--,pid=1740
进程4执行中--1--,pid=12232
进程5执行中--1--,pid=11420
进程3执行中--2--,pid=1740
进程4执行中--2--,pid=12232
进程5执行中--2--,pid=11420