Python多进程编程常用方法解析
本文深入解析Python中利用Multiprocessing包实现多进程编程的核心方法。重点讲解Process类的创建语法、参数传递、常用方法如start、join、terminate及属性daemon的使用。通过对比非守护进程与守护进程的执行差异,以及演示join在控制进程执行顺序中的作用,帮助开发者充分调用多核CPU资源,实现从单进程到并发执行的高效转换。
Python多进程编程概述
Python内置的多线程机制受全局解释器锁限制,并非真正的多线程并行。若要充分利用多核CPU的计算能力,在Python中通常需采用多进程方案。Python提供了功能完善的Multiprocessing包,开发者只需定义目标函数,该包即可自动处理其余底层工作。借助此包,可轻松实现从单进程到并发执行的平滑过渡。该模块支持子进程创建、进程间通信与共享数据、以及多种形式的同步机制,并提供了Process、Queue、Pipe、Lock等关键组件。
Process类详解
一、Process类基础
语法格式:Process([group[,target[,name[,args[,kwargs]]]]])
参数说明:target指定调用的目标函数;args为传递给目标函数的位置参数元组;kwargs为传递给目标函数的关键字参数字典。name用于指定进程别名,而groups参数在当前实现中通常未被使用。
常用方法:is_alive()用于检查进程是否仍在运行。
join(timeout):阻塞调用进程,直到被调用的子进程结束。timeout指定最大等待时间。
run():代表进程活动的方法,可在子类中重写。
start():启动子进程,并自动调用其run()方法。
terminate():立即终止进程,无论其是否正在执行任务。
属性包括:authkey、daemon(需在start()前设置)、exitcode(进程运行时为None,若为-N则表示被信号N终止)、name、pid。其中daemon属性决定父进程结束后子进程是否自动终止,且设置为True的进程不能创建新进程,必须在调用start()之前设置。
单进程与多进程创建示例
1. 创建函数并作为单个进程运行
from multiprocessing import Process
def func(name):
print("%s曾经是好人"%name)
if __name__ == "__main__":
p = Process(target=func,args=('kebi',))
p.start() #start()通知系统开启这个进程
2. 创建函数并将其作为多个并发进程运行
from multiprocessing import Process
import random,time
def hobby_motion(name):
print('%s喜欢运动'% name)
time.sleep(random.randint(1,3))
def hobby_game(name):
print('%s喜欢游戏'% name)
time.sleep(random.randint(1,3))
if __name__ == "__main__":
p1 = Process(target=hobby_motion,args=('付婷婷',))
p2 = Process(target=hobby_game,args=('科比',))
p1.start()
p2.start()
执行结果:
付婷婷喜欢运动 科比喜欢游戏
基于类的进程定义
3. 将进程定义为类(开启进程的另一种方法,并非最常用)
from multiprocessing import Process
class MyProcess(Process):
def __init__(self,name):
super().__init__()
self.name = name
def run(self): #start()时,run自动调用,而且此处只能定义为run。
print("%s曾经是好人"%self.name)
if __name__ == "__main__":
p = MyProcess('kebi')
p.start() #将Process当作父类,并且自定义一个函数。
Daemon属性与进程生命周期
4. 对比Daemon程序的效果
未设置daemon属性时
import time
def func(name):
print("work start:%s"% time.ctime())
time.sleep(2)
print("work end:%s"% time.ctime())
if __name__ == "__main__":
p = Process(target=func,args=('kebi',))
p.start()
print("this is over")
#执行结果
this is over
work start:Thu Nov 30 16:12:00 2017
work end:Thu Nov 30 16:12:02 2017
设置daemon属性后
from multiprocessing import Process
import time
def func(name):
print("work start:%s"% time.ctime())
time.sleep(2)
print("work end:%s"% time.ctime())
if __name__ == "__main__":
p = Process(target=func,args=('kebi',))
p.daemon = True #父进程终止后自动终止,不能产生新进程,必须在start()之前设置
p.start()
print("this is over")
#执行结果
this is over
若设置了daemon属性但仍希望执行完任务的方法:
import time
def func(name):
print("work start:%s"% time.ctime())
time.sleep(2)
print("work end:%s"% time.ctime())
if __name__ == "__main__":
p = Process(target=func,args=('kebi',))
p.daemon = True
p.start()
p.join() #执行完前面的代码再执行后面的
print("this is over")
#执行结果
work start:Thu Nov 30 16:18:39 2017
work end:Thu Nov 30 16:18:41 2017
this is over
join()同步机制与执行顺序控制
5. join()方法:上述代码执行完毕后,才会继续执行后续代码。
首先观察一个示例:
from multiprocessing import Process
import time,os,random
def func(name,hour):
print("A lifelong friend:%s,%s"% (name,os.getpid()))
time.sleep(hour)
print("Good bother:%s"%name)
if __name__ == "__main__":
p = Process(target=func,args=('kebi',2))
p1 = Process(target=func,args=('maoxian',1))
p2 = Process(target=func,args=('xiaoniao',3))
p.start()
p1.start()
p2.start()
print("this is over")
执行结果:
this is over #最后执行,最先打印,说明start()仅负责开启进程,并不保证立即执行完毕 A lifelong friend:kebi,12048 A lifelong friend:maoxian,8252 A lifelong friend:xiaoniao,6068 Good bother:maoxian #最先打印,第二位执行 Good bother:kebi Good bother:xiaoniao
添加join()后的效果
from multiprocessing import Process
import time,os,random
def func(name,hour):
print("A lifelong friend:%s,%s"% (name,os.getpid()))
time.sleep(hour)
print("Good bother:%s"%name)
start = time.time()
if __name__ == "__main__":
p = Process(target=func,args=('kebi',2))
p1 = Process(target=func,args=('maoxian',1))
p2 = Process(target=func,args=('xiaoniao',3))
p.start()
p.join() #上面的代码执行完毕之后,再执行后面的
p1.start()
p1.join()
p2.start()
p2.join()
print("this is over")
print(time.time() - start)
#执行结果
A lifelong friend:kebi,14804
Good bother:kebi
A lifelong friend:maoxian,11120
Good bother:maoxian
A lifelong friend:xiaoniao,10252 #每个进程执行完了,才会执行下一个
Good bother:xiaoniao
this is over
6.497815370559692 #2+1+3+主程序执行时间
调整代码位置后的行为
from multiprocessing import Process
import time,os,random
def func(name,hour):
print("A lifelong friend:%s,%s"% (name,os.getpid()))
time.sleep(hour)
print("Good bother:%s"%name)
start = time.time()
if __name__ == "__main__":
p = Process(target=func,args=('kebi',2))
p1 = Process(target=func,args=('maoxian',1))
p2 = Process(target=func,args=('xiaoniao',3))
p.start()
p1.start()
p2.start()
p.join() #需要2秒
p1.join() #到这时已经执行完
p2.join() #已经执行了2秒,还要1秒
print("this is over")
print(time.time() - start)
#执行结果
A lifelong friend:kebi,13520
A lifelong friend:maoxian,11612
A lifelong friend:xiaoniao,17064 #几乎是同时开启执行
Good bother:maoxian
Good bother:kebi
Good bother:xiaoniao
this is over
3.273620367050171 #以最长时间的为主
其他常用属性与方法
6. 其他属性和方法示例
from multiprocessing import Process
import time
def func(name):
print("work start:%s"% time.ctime())
time.sleep(2)
print("work end:%s"% time.ctime())
if __name__ == "__main__":
p = Process(target=func,args=('kebi',))
p.start()
p.terminate() #将进程杀死,而且必须放在start()后面,与daemon的功能类似
#执行结果
this is over
from multiprocessing import Process
import time
def func(name):
print("work start:%s"% time.ctime())
time.sleep(2)
print("work end:%s"% time.ctime())
if __name__ == "__main__":
p = Process(target=func,args=('kebi',))
# p.daemon = True
print(p.is_alive())
p.start()
print(p.name) #获取进程的名字
print(p.pid) #获取进程的pid
print(p.is_alive()) #判断进程是否存在
print("this is over")
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









