Python 的多进程编程主要通过 multiprocessing 模块实现。合理使用多进程可以提升 CPU 密集型任务的执行效率,但进程间通信也会带来额外复杂度。本文介绍 Python 多进程编程的基础知识,并重点讨论队列、管道、Manager 共享对象和共享内存等通信方式。

Python 多进程编程基础

multiprocessing 模块提供了 Process 类,用于创建新的进程。下面是一个简单的多进程编程例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import multiprocessing
import time

def worker(num):
print(f"Worker {num} is working...")
time.sleep(2) # 模拟一些工作
print(f"Worker {num} finished")

if __name__ == "__main__":
# 创建多个进程
processes = []
for i in range(5):
p = multiprocessing.Process(target=worker, args=(i,))
processes.append(p)
p.start()

# 等待所有进程完成
for p in processes:
p.join()

在这个例子中,我们创建了 5 个进程,每个进程执行 worker 函数。主进程等待所有进程完成后,程序结束。

进程间通信

在多进程编程中,进程间通信是一个重要问题。Python 的 multiprocessing 模块提供了几种进程间通信方法,包括队列、管道、Manager 共享对象、Value / Array 以及 shared_memory

1. 队列(Queue)

队列是最常用的进程间通信方法之一。队列是一种先进先出的数据结构,进程可以将数据放入队列中,其他进程可以从队列中取出数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import multiprocessing
import time

def worker(queue):
print("Worker is working...")
time.sleep(2) # 模拟一些工作
result = "Worker finished"
queue.put(result) # 将结果放入队列中

if __name__ == "__main__":
# 创建队列
queue = multiprocessing.Queue()

# 创建工作进程
p = multiprocessing.Process(target=worker, args=(queue,))
p.start()

# 等待工作进程完成
p.join()

# 从队列中获取结果
result = queue.get()
print(result)

2. 管道(Pipe)

管道是另一种进程间通信方法。multiprocessing.Pipe() 默认会返回一对双工连接,两端都可以发送和接收;如果创建时传入 duplex=False,才是单向管道。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import multiprocessing
import time

def worker(conn):
print("Worker is working...")
time.sleep(2) # 模拟一些工作
result = "Worker finished"
conn.send(result) # 发送结果
conn.close()

if __name__ == "__main__":
# 创建管道
parent_conn, child_conn = multiprocessing.Pipe()

# 创建工作进程
p = multiprocessing.Process(target=worker, args=(child_conn,))
p.start()

# 等待工作进程完成
p.join()

# 接收结果
result = parent_conn.recv()
print(result)
parent_conn.close()

3. Manager 共享对象

multiprocessing.Manager() 会启动一个管理进程,并返回可被其他进程访问的代理对象。下面的 manager.list() 不是严格意义上的共享内存,而是通过代理对象同步访问共享状态,适合小规模、结构化的共享数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import multiprocessing
import time

def worker(shared_list):
print("Worker is working...")
time.sleep(2) # 模拟一些工作
shared_list.append("Worker finished") # 修改共享列表

if __name__ == "__main__":
# 创建共享列表
manager = multiprocessing.Manager()
shared_list = manager.list()

# 创建工作进程
p = multiprocessing.Process(target=worker, args=(shared_list,))
p.start()

# 等待工作进程完成
p.join()

# 打印共享列表
print(list(shared_list))

4. 共享内存(Shared Memory)

如果需要让多个进程直接访问同一块内存区域,可以使用 Python 3.8+ 提供的 multiprocessing.shared_memory。它更适合传递大数组、图像缓冲区等数据,但需要手动管理内存生命周期。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from multiprocessing import Process, shared_memory

def worker(name):
shm = shared_memory.SharedMemory(name=name)
shm.buf[0] = 42
shm.close()

if __name__ == "__main__":
shm = shared_memory.SharedMemory(create=True, size=10)
p = Process(target=worker, args=(shm.name,))
p.start()
p.join()

print(shm.buf[0])
shm.close()
shm.unlink()

总结

Python 的多进程编程主要通过 multiprocessing 模块实现。多进程适合 CPU 密集型任务,而进程间通信可以通过队列、管道、Manager 代理对象和共享内存等方式完成。实际使用时,应根据数据量、通信方向和共享状态复杂度选择合适方案。