本文共 2431 字,大约阅读时间需要 8 分钟。
进程池是Python中一个强大的工具,用于高效管理多进程任务。对于需要同时执行大量任务但又不希望手动创建大量进程的情况,Python的multiprocessing
模块提供了Pool
功能,能够自动管理进程的数量和生命周期。
使用Pool
时,首先需要指定最大进程数。Pool
会根据需求自动创建新的进程来处理任务。当任务数量超过最大进程数时,会采用等待策略,等待现有的进程完成后再创建新的进程。例如,以下代码创建一个最多运行3个进程的池:
from multiprocessing import Poolimport os, time, randomdef worker(msg): t_start = time.time() print(f"{msg}开始执行,进程号为{os.getpid()}") time.sleep(random.random() * 2) t_stop = time.time() print(f"{msg}执行完毕,耗时{t_stop - t_start:.2f}")
po = Pool(3)for i in range(10): po.apply_async(worker, (i,))
运行上述代码时,池会自动分配任务给多个进程。每个进程会独立执行任务,并根据随机时间延迟后完成。这样可以显著提高任务处理效率。
Pool
提供了多个功能性方法,主要包括:
apply_async(func, [args], [kwds])
:非阻塞地提交任务给池执行。close()
:关闭池,停止接受新任务。terminate()
:立即终止所有进程,不管任务是否完成。join()
:阻塞主进程,等待所有子进程完成。在进程池中,进程间的通信通常需要通过Queue
实现。需要注意的是,multiprocessing
模块的Queue
必须通过Manager
创建,而不是直接使用multiprocessing.Queue
,否则会出现以下错误:
RuntimeError: Queue objects should only be shared between processes through inheritance.
以下示例展示了进程池中进程如何通过队列实现通信:
from multiprocessing import Manager, Poolimport os, time, randomdef reader(q): print(f"reader启动({os.getpid()}),父进程为({os.getppid()})") for i in range(q.qsize()): print(f"reader从Queue获取到消息:{q.get(True)}")def writer(q): print(f"writer启动({os.getpid()}),父进程为({os.getppid()})") for i in "helloworld": q.put(i)if __name__ == "__main__": print(f"({os.getpid()}) start") q = Manager().Queue() po = Pool() po.apply_async(writer, (q,)) time.sleep(1) po.apply_async(reader, (q,)) po.close() po.join() print(f"({os.getpid()}) End")
以下是一个更复杂的案例,展示了如何在多个进程之间通过队列进行通信和数据传递:
from multiprocessing import Manager, Poolimport os, time, randomdef reader(q): print(f"reader启动({os.getpid()}),父进程为({os.getppid()})") while True: if not q.empty(): print(f"reader从Queue获取到消息:{q.get(True)}") time.sleep(0.1)def writer(q): print(f"writer启动({os.getpid()}),父进程为({os.getppid()})") for i in range(5): msg = f"消息{i}" print(f"writer将消息'{msg}'添加到Queue") q.put(msg) time.sleep(0.2)if __name__ == "__main__": print(f"({os.getpid()}) start") q = Manager().Queue() po = Pool() po.apply_async(writer, (q,)) time.sleep(0.5) po.apply_async(reader, (q,)) po.close() po.join() print(f"({os.getpid()}) End")
通过以上案例可以看到,进程池和队列是实现多进程任务并行执行和通信的强大工具。在实际应用中,可以根据需求灵活配置池的大小和任务的执行策略,以达到最佳性能。
转载地址:http://gsavz.baihongyu.com/