更方便的管理进程
multiprocessing
步骤
1. 确定执行事件,将事件封装成函数
2. 使用Process 创建新的进程,将要执行的函数传入
的到相应的进程对象
***************************************
Process 参数
name : 起的新的进程名称
target: 传入的目标函数
args: 以元组的方式向目标函数进行位置传参
kwargs:以字典的方式向目标函数进行传参
***************************************
3.使用相应的对象调用start()属性函数启动子进程
4.使用响应对象调用 join()函数等待接受子进程退出
*************************************
import multiprocessing as mp
import os
from time import sleep
from random import randint
#定义函数
def worker():
sleep(randint(0,4))
print(os.getppid(),'-------',\
os.getpid())
print('worker')
jobs = []
print('This is parent:',os.getpid())
for i in range(5):
p = mp.Process(target = worker)
jobs.append(p)
p.start()
for i in jobs:
i.join()
进程对象 p 的属性
p.pid 响应子进程的PID号
p.name 子进程的 名字
p.is_alive() : 子进程状态
p.start() : 启动子进程
p.join([timeout]): 回收子进程函数 timeout是一个可选参数,表示超时等待时间。
import multiprocessing as mp
from time import sleep
import os
a = 100
def worker(sec,message):
for i in range(3):
sleep(sec)
print('the create message:',\
message)
print('in child process:',\
os.getppid())
print(a)
p = mp.Process(target = worker,\
name = 'Ketty',args = (2,),\
kwargs = {'message':'hello world'})
p.start()
print('pid:',p.pid) #子进程的PID
print('name:',p.name) #子进程的名字
print('is_alive',p.is_alive()) #状态
a = 100000
p.join() #等待3秒,如果不退出就不等了
print('*****main process over******')
print(a)
p.daemon : 默认为False 表示主进程执行结束后不会立即退出,而是等待子进程执行结束后再退出。
设置为 True ,那么主进程执行结束后会终止该子进程的执行,并且立即退出。必须在start前设置
run()
import multiprocessing as mp
from time import sleep
def fun():
print('child start')
sleep(3)
print('fun is over')
p = mp.Process(target = fun)
p.daemon = True
p.start()
sleep(0.1)
print("***main process over*****")
守护进程:系统中的后台服务进程。
特点:独立于终端并周期性的执行某种任务
生命周期长,一般随系统启动,随系统终止
进程缺点
进程的创建需要消耗较多的系统资源
进程池
多个进程执行任务
任务非常多,且执行时间短,需要频繁创建删除进程
1. 使用 Pool 创建进程池,得到进程池对象
2. 使用 apply_async 将事件放入进程池等待执行
3. 如果池内有空闲进程则会执行等待的事件
4. 使用close关闭进程池,不能够在投放进程
5. 使用join 阻塞等待进程池内现有所有事件都被执行结束后回收子进程(进程池内所有进程均为子进程)
进程池对象(pool)的方法:
异步加载事件到进程池
pool.apply_async(fun,[args = (),[kwargs = {}]])
同步加载事件到进程池
pool.apply(fun,[args = (),[kwargs = {}]])
close() 关闭进程池
join() 阻塞,等待进程池子进程退出。必须在close
后
import multiprocessing as mp
from time import sleep
import os
def worker(msg):
print(os.getpid())
sleep(2)
print(msg)
return
if __name__ == '__main__':
#创建一个包含四个进程的进程池,得到进程池对象pool
pool = mp.Pool(processes = 4)
result = []
for i in range(10):
msg = 'hello %d'%i
#向进程池中加载事件
# r = pool.apply(worker,(msg,)) #同步执行
r = pool.apply_async(worker,(msg,))
result.append(r)
# 得到每个事件的返回值 ,apply方法没有此功能
for res in result:
print(res.get())
#关闭进程池
pool.close()
#进程池回收
pool.join()
pool.map(fun, iterable)
功能上类似内建函数 map 将第二个参数中的每一个数带入到第一函数中进行传参。然后将该事件放入进程池
进程间通信
不同的进程间进行消息的传递。
文件 : 不好 , 文件可以被随意打开修改。和磁盘的交互也比较慢
管道 :
在内存中开辟的一块空间,对多个进程可见。在形式上有一定的约束。
* 通过 Pipe 创建,返回值有两个分别表示管道的两端。
* 当创建时参数为True(默认)时两个返回值均可以进行send和recv操作,当为false时,第一个可进行recv操作第二个可send。
* recv函数为阻塞函数,当管道内为空时会阻塞
import time
from multiprocessing import Pool
def run(fn):
time.sleep(1)
return fn*fn
test = [1,2,3,4,5,6]
print('顺序执行:')
s = time.time()
for fn in test:
run(fn)
e = time.time()
print('执行时间:',float(e - s))
print('多任务执行:')
pool = Pool(3)
# 兼顾了 apply_async
r = pool.map(run,test)
pool.close()
pool.join()
e1 = time.time()
print('执行时间:',float(e1 - e))