Python多进程编程依赖multiprocessing模块,通过Process类或Pool进程池实现并行计算,有效规避GIL限制,适用于CPU密集型任务。

Python实现多进程编程主要依赖其内置的
multiprocessing
要实现Python多进程编程,核心就是使用
multiprocessing
Process
举个例子,假设我们有一个耗时的计算任务:
import os
import time
from multiprocessing import Process, Queue
def compute_heavy_task(name, duration, output_queue=None):
"""一个模拟耗时计算的函数"""
pid = os.getpid()
print(f"进程 {name} (PID: {pid}) 启动,将运行 {duration} 秒。")
start_time = time.time()
result = 0
for _ in range(int(duration * 1000000)): # 模拟CPU密集型计算
result += 1
end_time = time.time()
print(f"进程 {name} (PID: {pid}) 完成,耗时 {end_time - start_time:.2f} 秒。")
if output_queue:
output_queue.put(f"结果来自 {name}: {result}")
if __name__ == '__main__':
print(f"主进程 (PID: {os.getpid()}) 启动。")
# 创建一个队列用于进程间通信
results_queue = Queue()
# 创建并启动多个进程
process1 = Process(target=compute_heavy_task, args=('Worker-1', 2, results_queue))
process2 = Process(target=compute_heavy_task, args=('Worker-2', 3, results_queue))
process3 = Process(target=compute_heavy_task, args=('Worker-3', 1, results_queue))
process1.start() # 启动进程1
process2.start() # 启动进程2
process3.start() # 启动进程3
# 等待所有子进程完成
process1.join()
process2.join()
process3.join()
print("所有子进程已完成。")
# 从队列中获取结果
while not results_queue.empty():
print(results_queue.get())
print("主进程结束。")在这个例子里,我们定义了一个
compute_heavy_task
if __name__ == '__main__':
Process
args
start()
join()
Queue
立即学习“Python免费学习笔记(深入)”;
除了直接使用
Process
multiprocessing
Pool
Pool
map
apply
starmap
import os
import time
from multiprocessing import Pool
def square(x):
"""一个简单的计算函数"""
pid = os.getpid()
print(f"进程 {pid} 正在计算 {x} 的平方...")
time.sleep(0.5) # 模拟一些工作
return x * x
if __name__ == '__main__':
print(f"主进程 (PID: {os.getpid()}) 启动。")
data = [1, 2, 3, 4, 5, 6, 7, 8]
# 创建一个包含4个工作进程的进程池
# 默认情况下,Pool会使用os.cpu_count()个进程
with Pool(processes=4) as pool:
# 使用map方法将data中的每个元素并行地传递给square函数
results = pool.map(square, data)
print("所有计算已完成。")
print("结果:", results)
print("主进程结束。")Pool
map
map
这大概是很多初学者都会困惑的问题,甚至连我刚开始接触Python并发编程时也一度搞不清楚。说白了,核心原因在于Python的全局解释器锁(Global Interpreter Lock,简称GIL)。
GIL是CPython解释器(也就是我们最常用的Python实现)的一个特性,它在任何时刻都只允许一个线程执行Python字节码。这意味着,即使你的机器有多个CPU核心,一个Python进程内的多个线程也无法真正并行地执行Python代码。它们会轮流获取GIL,交替执行,这对于I/O密集型任务(比如网络请求、文件读写,因为等待I/O时线程会释放GIL)来说影响不大,甚至能提高效率。
然而,对于CPU密集型任务(比如复杂的数学计算、数据处理),线程之间会频繁地争抢GIL。一个线程好不容易拿到GIL开始计算,没多久可能就被迫释放GIL让给其他线程,然后又得重新竞争。这种频繁的上下文切换和锁的竞争,反而会引入额外的开销,导致多线程版本的程序可能比单线程版本还要慢。这听起来有点反直觉,但这就是GIL的现实。
多进程则不同。每个进程都有自己独立的Python解释器实例和内存空间。这意味着每个进程都有自己独立的GIL,它们之间互不影响。当一个进程执行CPU密集型任务时,它拥有自己的GIL,可以完全占用一个CPU核心进行计算,而其他进程也可以同时在其他CPU核心上独立运行。因此,多进程能够真正地利用多核CPU的并行计算能力,是解决Python中CPU密集型任务性能瓶颈的有效手段。我个人觉得,理解GIL是深入Python并发编程的第一步,它直接决定了你选择多进程还是多线程。
multiprocessing
常见的陷阱:
multiprocessing
Queue
Pipe
Value
Array
Manager
Queue
Pipe
Pool
TypeError
if __name__ == '__main__':
if __name__ == '__main__':
fork
Queue
Lock
fork
最佳实践:
Pool
Pool
Process
map
apply
Queue
Pipe
Lock
Manager
os.cpu_count() + 1
try...except
join()
Pool
concurrent.futures.ProcessPoolExecutor
concurrent.futures
threading.ThreadPoolExecutor
Python处理并发任务的工具和模式远不止
multiprocessing
threading
threading
asyncio
asyncio
concurrent.futures
ThreadPoolExecutor
threading
ProcessPoolExecutor
multiprocessing
submit()
Future
Future
concurrent.futures
第三方库,例如joblib
joblib
Parallel
for
joblib
对我来说,选择哪种工具,很大程度上取决于任务的性质。CPU密集型任务,我果断会考虑
multiprocessing
concurrent.futures.ProcessPoolExecutor
threading
asyncio
joblib
Parallel
以上就是python如何实现多进程编程_python multiprocessing模块多进程编程实践的详细内容,更多请关注php中文网其它相关文章!
python怎么学习?python怎么入门?python在哪学?python怎么学才快?不用担心,这里为大家提供了python速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号