上一篇文章中,通过os模块简单演示了多进程的使用。但是os.fork()函数只能在在Linux内核的操作系统中执行,在Windows上无法执行。所以,上一篇文章中演示的代码在Windows上跑不起来。本文就来通过Python更加强大的内置模块multiprocessing模块来编写可移植的多进程代码。
本文的主要内容有:
1、Process类的简单介绍
2、通过Process构造函数创建子进程
3、通过继承Process类创建子进程
Process类的简单介绍如同多线程编程中,通过Thread类实现线程对象的抽象封装。在Python中,类比Thread类,创建了Process类,实现了对进程对象的抽象封装,从而可以更加轻易地管理进程对象。
在真正使用Process类之前,首先来看下Process类中的常用方法和属性。
1、__init__()初始化方法
如同Thread构造函数的用法一样,通常只需要传入target参数和args参数,即可快速创建一个进程对象。
2、is_alive()方法
用于判断进程是否在运行,仍在运行,则返回True,否则False。
3、join(timeout=None)方法
等待调用该方法的进程执行终止或者超时才执行后续的代码。
4、start()方法
如同线程对象一样,构造之后,并不会自行运行起来,需要通过start()方法才能真正启动一个子进程。
5、run()方法
进程真正执行的业务逻辑,都会在run()方法中执行。如同通过继承的方式创建子线程一样,也可以通过继承Process类,并重写run()方法,来实现自定义进程。
6、terminate()方法
该方法用于强制终止一个进程。如果调用了该方法,则进程会立即终止,同时不会进行任何清理动作。如果该进程创建了自己的子进程,则这些子进程会变成僵尸进程。所以,使用该方法需要特别小心。如果该进程保存了一个锁或者参与了进程间通信,那么强制终止它,可能会导致死锁或者IO损坏。
7、name属性
可以在初始化方法中自定义进程的名称,也可以通过name这个property自行修改。
8、daemon属性
daemon属性是一个布尔值,用于标识该进程是否为守护进程/后台进程,关于守护进程的概念,可以类比之前提到的守护线程的概念。
一个进程的daemon属性只有在start()方法调用之前进行设置。
一个进程如果被设置为守护进程,则创建该守护进程的进程终止时,守护进程会自动终止。此外,守护进程不允许被创建自己的子进程。
9、exitcode属性
是一个整数,标识进程的退出代码。如果仍在运行,则返回None,如果为负数,-N表示进程对象是由信号N所终止。
10、pid属性
用于标识进程的ID,只有进程对象启动起来,才会有PID,否则为None。
有了上面关于进程的方法和属性的了解,就可以简单地使用Process类进行多进程的代码编写了。
如同Thread类进行多线程代码编写有两种方式一样,Process类的多进程创建也是有两种方式,接下来分别通过代码演示这两种方法。
通过Process构造函数创建子进程如果子进程要执行的业务逻辑比较简单,可以通过这种方式进行子进程的创建,主要步骤如下:
1、定义函数封装要执行的业务逻辑
2、将函数及其参数作为Process类的初始化方法的参数,用于子进程对象的创建及初始化
3、调用子进程对象的start()方法启动该子进程的执行
接下来看具体代码:
执行结果:
这一次是通过多进程的方式实现了一个时钟的效果,之前有通过Timer实现过类似的需求。
从代码的执行可以看到,在进程对象调用start()方法之前,是pid为None,存活状态为False。只有真正被调用start()方法启动之后,才有具体的值被设置。
可以理解为进程实际上是一个动态执行的对象,一个Process对象在启动之前,在操作系统感知来看,都不是一个真正的进程。
通过继承Process类创建子进程直接通过Process的初始化方法创建子进程的方法,非常简单。接下来,通过类继承的方式创建子进程。该方法主要有以下步骤:
1、自定义类继承Process类
2、初始化方法中需要显式调用父类的初始化方法
3、重写run()方法,实现业务逻辑的封装
4、创建自定义进程对象并调用start()方法
直接看代码:
执行结果跟第一种方式一样,就不再贴出来了。
这种通过继承的方式,更适合业务逻辑比较复杂的场景。
最后,需要特别说明的是,我们都是在main语法块中进行子进程的创建和启动的,这一点在Linux或者Mac上不是必须的,但是在Windows中是必须的,否则可能会抛出异常。考虑到兼容性,尽量在main语法块创建子进程吧。
总结本文简单介绍了multiprocessing模块中的Process类的常用方法和几个核心属性。并通过具体代码演示了子进程创建的两种方式。Python中的多进程与多线程在设计、编程接口上是很相似的,所以,真正上手起来并不复杂。
以上就是本文的全部内容了,感谢您的拨冗阅读。