本文继续Python多任务编程思想(一)的话题,讨论python中进程的剩余几个概念:守护进程、重写Process类创建子进程以及进程池技术。
一.守护进程
主进程创建守护进程:①设置daemon属性为true;②虽然进程间是相互独立的,守护进程会在主进程"代码执行结束"时终止;③守护进程中不能再创建子进程。
守护进程与守护线程存在很大差异,在学习完守护线程后,将对二者做出总结区分。
代码示例:
'''p1为守护进程,在主进程退出时,p1结束循环;p2为非守护进程,不会受到主进程的影响'''
from multiprocessing import Process
import time
import os
import signal
def foo():
while True:
print(time.ctime())
time.sleep(3)
def bar():
print("非守护进程启动")
time.sleep(10)
print("非守护进程结束")
p1=Process(target=foo)
p2=Process(target=bar)
#避免守护进程成为僵尸进程
signal.signal(signal.SIGCHLD, signal.SIG_IGN)
if __name__ == '__main__':
p1.daemon=True
p1.start()
p2.start()
print("守护进程:",p1.pid)
print("非守护进程:",p2.pid)
time.sleep(4)
print("主进程{}结束!".format(os.getpid()))
二.创建自己的进程类:
1.继承Process类
2.重写__init__ 方法,并且调用父类的__init__
3.重写run方法:生成对象后调用start方法,自动运行run
'''创建自己的进程类
①继承Process类
②重写__init__ 并且调用父类的__init__
③重写run方法,此时生成对象后调用start就会自动运行run
'''
from multiprocessing import Process
import time
class ClockProcess(Process):
def __init__(self, value):
# 调用父类的__init__方法
super().__init__()
self.value = value
def run(self):
'''重写run方法,子进程启动后,自动执行此方法'''
for i in range(3):
time.sleep(self.value)
print(time.ctime())
# 创建子进程
p1 = ClockProcess(2)
p1.start()
p1.join()
三.进程池技术
背景:多进程编程能并行执行多个任务,具有效率高,创建方便,运行独立,不受其他进程影响,数据安全等特点;但进程的创建和删除都需要消耗计算机的资源。如果有大量任务需要多进程完成,且可能需要频繁地创建和删除进程,将给计算机带来大量的资源消耗。
原理:在进程池内运行一定数量的进程,通过这些进程完成进程池队列中的事件,直到事件执行完,减少进程的不断地创建删除过程。
实现:
①创建进程池,在进程池中放入适当进程
②将事件加入到进程池队列
③事件不断运行,直到所有事件运行完毕
④关闭进程池,回收进程
from multiprocessing import Pool
pool = Pool(processes) #创建进程池对象;参数:表示进程池中有多少进程
pool.apply_async(func, args, kwds) #将事件放入进程池队列
参数:func 要执行的事件,args 给func用元组传参,kwds 给func用字典传参
返回值:返回事件对象 通过get()方法获取事件函数返回值
pool.map(func,iter) #将要完成的事件放入进程池
参数:func 要完成的事件函数,iter 可迭代对象给func传值
返回值:时间函数的返回值列表
pool.close() #关闭进程池,不能再添加新的事件
pool.join() #阻塞等待回收进程池
方法一:apply_async
'''方式一:使用"apply_async()"需要自己创建列表,维护返回值'''
from multiprocessing import Pool
from time import sleep,ctime
def event(message):
sleep(2)
print(ctime(),':',message)
return '&' + str(message) + '&'
print(ctime())
pool = Pool(4)
r_list = []
for i in range(10):
# apply效率非常低,进程池中同一时刻,只有一个进程在运行。程序在此处阻塞
# element = pool.apply(event,(i,))
# apply_async可以提升效率:进程池中的进程并行执行,一起返回,直到所有进程都执行完毕;
# 程序在此处并不会阻塞
element = pool.apply_async(event,(i,))
print(element)
r_list.append(element)
for e in r_list:
# print(e)
# apply_async返回事件对象,可通过get()方法获取事件函数返回值
print(e.get())
print(ctime())
pool.close()
pool.join()
方法二. map
'''方法二 使用进程池的map方法;返回值为列表,无需自己创建维护列表'''
from multiprocessing import Pool
from time import sleep,ctime
def event(message):
sleep(1)
print(ctime(),':',message)
return '&' + str(message) + '&'
pool = Pool(4)
print(ctime())
# 阻塞,返回值为列表
l = pool.map(event, range(10))
# 非阻塞,返回值为对象,使用get()方法获取列表,get()会阻塞
# l = pool.map_async(event, range(10))
print(l)
# print(l.get())
pool.close()
pool.join()
print(ctime())