当前位置:首页 > Python > 正文

Python Process创建进程的两种方法详解 | Python多进程编程教程

Python多进程编程:创建进程的两种方法详解

全面解析使用multiprocessing模块创建进程的两种方法,包含代码示例、性能对比和最佳实践

在Python中,多进程是实现并行计算和充分利用多核CPU的重要技术。与多线程不同,多进程可以绕过GIL(全局解释器锁)的限制,真正实现并行执行。本教程将详细讲解Python中创建进程的两种主要方法,并提供实际代码示例。

为什么使用多进程?

Python的GIL限制了同一时刻只能有一个线程执行Python字节码,这使得多线程在CPU密集型任务中无法充分利用多核处理器。多进程通过创建独立的Python解释器进程,每个进程有自己的GIL,从而实现了真正的并行执行。

CPU密集型任务

对于需要大量计算的任务(如数学计算、图像处理),多进程可以显著提高执行速度

隔离性

进程间内存空间相互隔离,一个进程崩溃不会影响其他进程

充分利用多核

每个进程可以在不同的CPU核心上运行,充分利用现代多核处理器

方法一:使用函数创建进程

这是最直接的方法,通过创建multiprocessing.Process实例并传入目标函数来创建新进程。

步骤:

  1. 导入multiprocessing模块
  2. 定义目标函数
  3. 创建Process对象,指定目标函数和参数
  4. 启动进程
  5. 等待进程结束(可选)
import multiprocessing
import os
import time

# 定义目标函数
def worker_process(task_id, delay):
    print(f"进程 {task_id} (PID: {os.getpid()}) 开始执行,延迟 {delay}秒")
    time.sleep(delay)
    print(f"进程 {task_id} 完成")

if __name__ == '__main__':
    # 创建进程列表
    processes = []
    
    # 创建并启动三个进程
    for i in range(3):
        p = multiprocessing.Process(
            target=worker_process,  # 目标函数
            args=(i, i+1)           # 传递给函数的参数
        )
        processes.append(p)
        p.start()
        print(f"主进程: 启动了进程 {i}")
    
    # 等待所有进程完成
    for p in processes:
        p.join()
    
    print("所有进程执行完毕!")

代码解析:

  • multiprocessing.Process:进程类,用于创建新进程
  • target:指定要在新进程中运行的函数
  • args:传递给目标函数的参数(以元组形式)
  • start():启动进程
  • join():阻塞当前进程,直到目标进程完成
  • if __name__ == '__main__':在Windows系统中必须使用,避免子进程无限递归

方法二:通过继承Process类创建进程

这种方法通过创建Process的子类并重写run()方法来实现自定义进程行为。

步骤:

  1. 导入multiprocessing模块
  2. 创建Process的子类
  3. 重写__init__方法(可选)
  4. 重写run()方法,定义进程执行逻辑
  5. 实例化自定义进程类
  6. 启动进程
import multiprocessing
import os
import time

# 自定义进程类
class CustomProcess(multiprocessing.Process):
    def __init__(self, task_id, delay):
        super().__init__()  # 调用父类初始化
        self.task_id = task_id
        self.delay = delay
    
    def run(self):
        """重写run方法,定义进程执行内容"""
        print(f"自定义进程 {self.task_id} (PID: {os.getpid()}) 开始执行")
        time.sleep(self.delay)
        print(f"自定义进程 {self.task_id} 完成,耗时 {self.delay}秒")

if __name__ == '__main__':
    # 创建自定义进程实例
    processes = [
        CustomProcess(i, i+1) for i in range(3)
    ]
    
    # 启动所有进程
    for p in processes:
        p.start()
    
    # 等待进程完成
    for p in processes:
        p.join()
    
    print("所有自定义进程执行完毕!")

代码解析:

  • 继承multiprocessing.Process
  • 重写__init__方法时,必须调用父类的__init__
  • run()方法:定义进程启动后执行的操作
  • 通过调用start()方法启动进程,会自动调用run()方法
  • 这种方法更适合需要封装复杂逻辑的进程

进程创建过程可视化

主进程
(PID: 1234)
进程 0
(PID: 5678)
进程 1
(PID: 9012)
进程 2
(PID: 3456)

主进程创建并启动多个子进程,每个子进程拥有独立的PID和内存空间

函数式创建进程

优点:

  • 简单直观,适合简单任务
  • 代码量少,易于理解
  • 不需要创建新类
  • 与现有函数集成方便

缺点:

  • 不适合复杂逻辑
  • 状态管理不够灵活
  • 进程相关功能扩展性有限

继承式创建进程

优点:

  • 封装性好,适合复杂任务
  • 可以添加额外方法和属性
  • 更好的代码组织和复用性
  • 便于扩展进程功能

缺点:

  • 需要创建新类,代码量稍多
  • 学习曲线稍陡峭
  • 对于简单任务可能过度设计

多进程编程最佳实践

进程间通信

使用Queue、Pipe或共享内存进行进程间通信,避免使用全局变量

资源管理

使用with语句或确保在finally块中释放资源,避免资源泄漏

进程池

对于大量任务,使用multiprocessing.Pool管理进程更高效

重要注意事项

  • Windows系统限制:在Windows上必须使用if __name__ == '__main__'保护入口点
  • 进程间隔离:进程不共享内存,修改父进程变量不会影响子进程
  • 资源消耗:创建进程比线程开销更大,进程数量不宜过多
  • 进程间通信:需要使用特定机制(Queue、Pipe等)进行数据交换
  • 可序列化:传递给子进程的参数和返回值必须是可序列化的

Python多进程编程教程 | 两种创建进程方法详解

掌握多进程技术,释放你的CPU全部潜力!

发表评论