111、Python并发编程:使用multiprocessing模块编写可移植的多进程

南宫理的日志录 2024-12-04 10:30:19
引言

上一篇文章中,通过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中的多进程与多线程在设计、编程接口上是很相似的,所以,真正上手起来并不复杂。

以上就是本文的全部内容了,感谢您的拨冗阅读。

0 阅读:0

南宫理的日志录

简介:深耕IT科技,探索技术与人文的交集