Python中的进程(python中的进程和线程)

网友投稿 325 2022-08-30


Python中的进程(python中的进程和线程)

Python中的进程

​​一、前言​​​​二、创建进程的常用方式​​

​​1.使用multiprocessing模块创建进程​​​​2.使用Process子类创建进程​​​​3.使用进程池Pool创建进程​​

​​三、通过队列实现进程间通信​​

一、前言

二、创建进程的常用方式

在Python中有多个模块可以创建进程,比较常用的有os.fork()函数、multiprocessing模块和Pool进程池。由于os.fork()函数只适用于Unix/Linux/Mac系统上运行,所以本文重点介绍multiprocessing模块和Pool进程池这两个跨平台模块。

1.使用multiprocessing模块创建进程

multiprocessing模块提供了一个Process类来代表一个进程对象,语法如下:

process(group[,target[,name[,args[,kwargs]]]])

Process类的参数说明如下:

group:参数未使用,值始终为None。target:表示当前进程启动时执行的可调用对象。name:为当前进程实例的别名。agrs:表示传递给target函数的参数元组。kwargs:表示传递给target函数的参数字典。

例如,实例化Process类,执行子进程,代码如下:

from multiprocessing import Process# 执行子进程代码def test(interval): print("我是子进程")# 执行主程序def main(): print("主进程开始") p = Process(target=test, args=(1,)) # 实例化Process进程类 p.start() # 启动子程序 print("主程序结束")if __name__ == "__main__": main()

上述代码中,先实例化Process类,然后使用p.start()方法启动子进程,开始执行test()函数。Process的实例p常用的方法除start()外,还有如下常用的方法:

is_alive():判断进程实例是否还在执行。join([timeout]):是否等待进程实例执行结束,或等待多少秒。start():启动进程实例(创建子进程)run():如果没有给定target参数,对这个对象调用start()方法时,就将执行对象中的run()方法。terminate():不管任务是否完成,立即终止。

Process类还有如下常用属性:

name:当前进程实例别名,默认为Proc-N,N为从1开始递增的整数。pid:当前进程实例的PID值。

下面通过一个简单示例演示Process类的方法和属性的使用,创建2个子进程,分别使用os模块和time模块输出父进程和子进程的ID以及子进程的时间,并调用Process类的name和pid属性,代码如下:

# _*_ coding:utf-8 _*_from multiprocessing import Processimport timeimport os# 两个子进程将会调用的两个方法def child_1(interval): print("子进程(%s)开始执行,父进程为(%s)" % (os.getpid(), os.getppid())) t_start = time.time() # 计时开始 time.sleep(interval) # 程序将会被挂起interval秒 t_end = time.time() # 计时结束 print("子进程(%s)执行时间为'%0.2f'秒" % (os.getppid(), t_end - t_start))def child_2(interval): print("子进程(%s)开始执行,父进程为(%s)" % (os.getpid(), os.getppid())) t_start = time.time() # 计时开始 time.sleep(interval) # 程序将会被挂起interval秒 t_end = time.time() # 计时结束 print("子进程(%s)执行时间为'%0.2f'秒" % (os.getppid(), t_end - t_start))if __name__ == "__main__": print("-----------------父进程开始执行-------------") print("父进程PID:%s" % os.getpid()) # 输出当前程序的PID p1 = Process(target=child_1, args=(1,)) # 实例化进程p1 p2 = Process(target=child_2, name='mrsoft', args=(1,)) # 实例化进程p2 p1.start() # 启动进程p1 p2.start() # 启动进程p2 # 同时父进程乃然往下执行,如果p2进程还在执行,将会返回True print("p1.is_alive=%s" % p1.is_alive()) print("p2.is_alive=%s" % p2.is_alive()) # 输出p1和p2进程的别名和PID print("p1.is_alive = %s" % p1.name) print("p1.pid=%s" % p1.pid) print("p2.is_alive = %s" % p2.name) print("p2.pid=%s" % p2.pid) print("----------------等待子进程-------------------") p1.join() # 等待p1进程结束 p2.join() # 等待p2进程结束 print("----------父进程执行结束----------------------")

2.使用Process子类创建进程

对于一些简单的小任务,通常使用Process(target=test)方式实现多进程。但是如果要处理复杂任务的进程,通常定义一个类,使其进程Process类,每次实例化这个类的时候,就等同于实例化一个进程对象。下面,通过一个实例来学习一下如何通过使用Process子类创建多个进程。

使用Process子类方式创建2个子进程,分别输出父、子进程的PID,已经子进程的运行状态和运行时间,代码如下:

# _*_ coding:utf-8 _*_from multiprocessing import Processimport timeimport os# 继承Process类class Subprocess(Process): # 由于Process类本身也有__init__初始化方法,这个子类相当于重写了父类的这个方法 def __init__(self, interval, name=''): Process.__init__(self) # 调用Process父类的初始化方法 self.interval = interval # 接收参数interval if name: self.name = name # 如果传递参数name,则为子进程创建name属性,否则使用默认属性 # 重写了Process类的run()方法 def run(self): print("子进程(%s)开始执行,父进程为(%s)" % (os.getpid(), os.getppid())) t_start = time.time() time.sleep(self.interval) t_stop = time.time() print("子进程(%s)执行结束,耗时%0.2f秒" % (os.getpid(), t_stop - t_start))if __name__ == "__main__": print("------------父进程开始执行-----------") print("父进程PID:%s" % os.getpid()) # 输出当前程序的ID p1 = Subprocess(interval=1, name='mrsoft') p2 = Subprocess(interval=2) # 对一个不包含target属性的Process类执行start()方法,就会运行这个类中的run()方法 # 所以这里会执行p1.run() p1.start() # 启动p1进程 p2.start() # 启动p2进程 # 输出p1和p2进程的执行状态,如果真正进行,返回True;否则返回False print("p1.is_alive=%s" % p1.is_alive()) print("p2.is_alive=%s" % p2.is_alive()) # 输出p1和p2进程的别名和PID print("p1.name = %s" % p1.name) print("p1.pid=%s" % p1.pid) print("p2.name = %s" % p2.name) print("p2.pid=%s" % p2.pid) print("----------------等待子进程-------------------") p1.join() # 等待p1进程结束 p2.join() # 等待p2进程结束 print("----------父进程执行结束----------------------")

3.使用进程池Pool创建进程

前面我们使用Process类创建了2个进程。如要要创建几十个或者上百个进程,则需要更多个Process类。有没有更好的创建进程方式解决这类问题呢?答案就是使用mulitprocessing模块提供的Pool类,即Pool进程池。

接下来,先来了解一下Pool类的常用方法。常用方法及说明如下:

apply_async(func[,args[,kwds]]):使用非阻塞方式调用func()函数(并执行,堵塞方式必须等待上一个进程退出才能执行下一个进程),args为传递func()函数的参数列表,kwds为传递给func()函数的关键字参数列表。apply(func[,args[,kwds]]):使用阻塞方式调用func()函数。close():关闭Pool,使其不再接受新的任务。terminate():不管任务是否完成,立即终止。join():主进程阻塞,等待子进程的退出,必须在close或terminate之后使用。

下面通过一个示例演示一下如何使用进程池创建多进程。这里模拟水池放水的场景,定义一个进程池,设置最大进程数为3。然后使用非阻塞方式执行10个任务,查看每个进程执行的任务。具体代码如下:

# _*_ coding:utf-8 _*_from multiprocessing import Poolimport timeimport osdef task(name): print("子进程(%s)执行task %s ..." % (os.getpid(), name)) time.sleep(1) # 休眠1秒if __name__ == "__main__": print("父进程(%s)." % os.getppid()) p = Pool(3) # 定义一个进程池,最大进程数为3 for i in range(10): p.apply_async(task, args=(i,)) # 使用非阻塞方式调用函数task()函数 print("等待所有子进程结束...") p.close() p.join() print("所有子进程结束.")

三、通过队列实现进程间通信

预知详情,请期待下篇,关注 ζ小菜鸡,让我们一起学习,咱们顶峰相见(๑•̀ㅂ•́)و✧


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:蓝桥杯每日一练:字符串对比(蓝桥杯字符串比较)
下一篇:蓝桥杯每日一练:矩形面积交(蓝桥杯基础题)
相关文章

 发表评论

暂时没有评论,来抢沙发吧~