Python多进程编程技术概述

进程是系统进行资源分配和调度的基本单位,拥有独立的地址空间。与线程相比,进程由于资源独立,运行更为稳定。另一方面,进程却不如线程轻量,创建开销更大。

合理应用多进程编程技巧,对提升程序多核处理能力意义重大。然而,进程使用方法因操作系统而异,操作系统原生多进程编程 API 也是五花八门。 Python 将进程编程 原语 进一步抽象,并提供一套简洁的通用 API ,复杂度已降到最低。

接下来,我们以一个最简单的例子,一览为快。

假设,我们需要启动 3 个进程,并行执行下面这个函数:

1
2
3
>>> def foo():
...     print('hello')
...

首先,我们从标准库 multiprocessing 包中导入 Process 类:

1
>>> from multiprocessing import Process

顾名思义,Process 类用于创建进程对象。我们通过列表推导创建 3 个进程对象:

1
>>> processes = [Process(target=foo) for _ in range(3)]

注意到,foo 函数作为 target 参数传给了 Process 类。 当 Process 对象启动时,将自动执行 target 指定的 可调用对象 。 它可以是一个函数,也可以是一个对象的某个方法。

现在,我们看到刚创建的进程处于 initial ,即初始状态:

1
2
>>> processes
[<Process(Process-1, initial)>, <Process(Process-2, initial)>, <Process(Process-3, initial)>]

初始状态表示进程对象完成了创建,但仍未启动,更别说执行 foo 函数了。

接下来,我们调用进程对象 start 方法,将进程逐个启动:

1
2
3
4
5
6
>>> for process in processes:
...     process.start()
...
hello
>>> hello
hello

我们刚启动进程,并陆续看到了它们执行 foo 函数而输出的 hello ,共 3 个。

注意到,有两个 hello 是在提示符出现后才输出的,这是操作系统未能及时调度的缘故。由于进程执行顺序与操作系统调度策略有关,因此不能对子进程执行顺序做任何假设。

由于 foo 函数非常简短,进程很快就执行完毕,并自动停止:

1
2
>>> processes
[<Process(Process-1, stopped)>, <Process(Process-2, stopped)>, <Process(Process-3, stopped)>]

进程虽然已经执行完毕并停止了,但它们占用的系统资源却仍未释放。因此,别忘了在进程停止后,调用 join 方法将其占用的系统资源进行释放:

1
2
3
>>> for process in processes:
...     process.join()
...

需要特别注意,如果进程还在运行, join 方法将一直阻塞,直到进程退出后才返回。

【小菜学Python】系列文章首发于公众号【小菜学编程】,敬请关注:

【小菜学Python】系列文章首发于公众号【小菜学编程】,敬请关注: