Python 中的进程(Process)

进程是操作系统进行资源分配和调度的基本单位 ,每个进程都有独立的内存空间文件描述符代码和数据 。Python 通过 multiprocessing 模块支持多进程编程。

一、进程 vs 线程

特性 进程 线程
内存空间 独立,互不干扰 共享同一进程的内存
数据隔离 天然隔离,需要 IPC 共享数据需要加锁
创建开销 大(需要复制内存)
切换开销 大(切换页表)
GIL 影响 无,真正的并行 有,受 GIL 限制
适用场景 CPU 密集型 I/O 密集型
复制代码
# 进程的独立内存空间
from multiprocessing import Process

data = []  # 全局列表

def worker():
    data.append(1)  # 每个进程有自己 copy 的 data
    print(f"{id(data)}: {data}")

p1 = Process(target=worker)
p2 = Process(target=worker)
p1.start()
p2.start()
p1.join()
p2.join()
# 输出:不同内存地址的进程各自操作自己的 data

二、创建进程的方式

1. 使用 Process

复制代码
from multiprocessing import Process
import os

# 方式1:传入目标函数
def worker(name, num):
    print(f"进程 {name}: PID={os.getpid()}, 父进程={os.getppid()}")
    return num * 2

p = Process(target=worker, args=("worker1", 100))
p.start()      # 启动进程
p.join()       # 等待进程结束
print(f"exit code: {p.exitcode}")

# 方式2:自定义进程类
class MyProcess(Process):
    def __init__(self, name):
        super().__init__()
        self.name = name
    
    def run(self):
        print(f"运行进程: {self.name}")

p = MyProcess("my_worker")
p.start()
p.join()

2. 进程启动方式(spawn vs fork)

复制代码
import multiprocessing as mp

# 设置启动方式(必须在 if __name__ == '__main__' 内)
if __name__ == '__main__':
    mp.set_start_method('spawn')  # Windows 默认,macOS 可选
    # 或 mp.set_start_method('fork')   # Linux 默认

# 三种启动方式对比:
# | 方式    | 特点                           | 适用平台    |
# |--------|-------------------------------|-----------|
# | spawn  | 全新启动,不继承父进程资源       | Windows    |
# | fork   | 复制父进程,继承资源(不安全)    | Linux/macOS|
# | forkserver| 通过服务进程 fork(安全)       | Unix-like  |

三、进程池(Pool)

复制代码
from multiprocessing import Pool
import time

def cpu_intensive(n):
    """CPU 密集型任务"""
    return sum(i * i for i in range(n))

def io_bound(n):
    """I/O 密集型任务"""
    time.sleep(n)
    return n

if __name__ == '__main__':
    # 创建进程池(默认 CPU 核心数)
    with Pool(processes=4) as pool:
        # 方式1:map(阻塞,保持顺序)
        results = pool.map(cpu_intensive, [10**7] * 4)
        
        # 方式2:map_async(非阻塞)
        result = pool.map_async(cpu_intensive, [10**7] * 4)
        print("异步提交完成")
        results = result.get()  # 等待结果
        
        # 方式3:apply(同步)
        result = pool.apply(cpu_intensive, (10**7,))
        
        # 方式4:apply_async(异步)
        async_result = pool.apply_async(cpu_intensive, (10**7,))
        result = async_result.get(timeout=30)
        
        # 方式5:starmap(多参数)
        args = [(1, 2), (3, 4), (5, 6)]
        results = pool.starmap(lambda a, b: a + b, args)

四、进程间通信(IPC)

1. Queue(队列)

复制代码
from multiprocessing import Process, Queue
import time

def producer(q):
    for i in range(5):
        q.put(f"消息{i}")
        print(f"生产: {i}")
        time.sleep(0.5)
    q.put(None)  # 结束标志

def consumer(q):
    while True:
        msg = q.get()
        if msg is None:
            break
        print(f"消费: {msg}")
        time.sleep(1)

if __name__ == '__main__':
    q = Queue(maxsize=10)  # 指定最大容量
    p1 = Process(target=producer, args=(q,))
    p2 = Process(target=consumer, args=(q,))
    p1.start()
    p2.start()
    p1.join()
    p2.join()

2. Pipe(管道)

复制代码
from multiprocessing import Process, Pipe

def worker(conn):
    """子进程通过管道发送数据"""
    conn.send([1, 2, 3])      # 发送对象
    print(f"收到父进程消息: {conn.recv()}")
    conn.close()

if __name__ == '__main__':
    # 创建双向管道
    parent_conn, child_conn = Pipe()
    
    p = Process(target=worker, args=(child_conn,))
    p.start()
    
    print(f"收到子进程数据: {parent_conn.recv()}")
    parent_conn.send("来自父进程的问候")
    p.join()

3. Shared Memory(共享内存)

复制代码
from multiprocessing import Process, Value, Array

def worker(val, arr):
    val.value += 1
    for i in range(len(arr)):
        arr[i] += i

if __name__ == '__main__':
    # 创建共享变量
    num = Value('i', 0)      # 'i' 表示有符号整数
    arr = Array('d', [0.0, 1.0, 2.0])  # 'd' 表示 double
    
    processes = []
    for _ in range(4):
        p = Process(target=worker, args=(num, arr))
        processes.append(p)
        p.start()
    
    for p in processes:
        p.join()
    
    print(f"num: {num.value}")
    print(f"arr: {arr[:]}")

共享内存类型码

类型码 C 类型 Python 类型
'i' int 有符号整数
'I' unsigned int 无符号整数
'l' long 有符号长整数
'f' float 浮点数
'd' double 双精度浮点数
'c' char 字符

4. Manager(管理器)

复制代码
from multiprocessing import Process, Manager

def worker(d, l, key, value):
    d[key] = value
    l.append(value)

if __name__ == '__main__':
    with Manager() as manager:
        # 创建共享字典和列表
        d = manager.dict()
        l = manager.list()
        
        processes = []
        for i in range(5):
            p = Process(target=worker, args=(d, l, f"key{i}", i))
            processes.append(p)
            p.start()
        
        for p in processes:
            p.join()
        
        print(f"dict: {d}")
        print(f"list: {l}")

五、进程同步(锁)

复制代码
from multiprocessing import Process, Lock, Value
import time

def worker(lock, counter):
    for _ in range(1000):
        lock.acquire()
        try:
            counter.value += 1
        finally:
            lock.release()

if __name__ == '__main__':
    counter = Value('i', 0)
    lock = Lock()
    
    processes = [Process(target=worker, args=(lock, counter)) for _ in range(10)]
    
    for p in processes:
        p.start()
    for p in processes:
        p.join()
    
    print(f"最终值: {counter.value}")  # 应该是 10000

其他

同步 用途
Lock 互斥锁,一次只能一个进程访问
RLock 可重入锁,同一进程可多次获取
Semaphore 信号量,限制并发数量
Event 事件,用于进程间信号通知
Condition 条件变量,复杂同步

核心点

  1. 进程内存隔离,数据不共享(与线程不同)

  2. 创建进程需要 if __name__ == '__main__'

  3. 进程适合 CPU 密集型任务

  4. 进程间通信使用 QueuePipeManager

  5. 共享可变数据需要加锁

  6. 进程创建开销大,使用进程池复用

相关推荐
XLYcmy3 小时前
京东 算法实习一面 下+手撕
c++·python·llm·概率论·数据处理·训练·codebert
虎头金猫3 小时前
如何在群晖NAS上通过Docker部署CloudSaver?群晖部署CloudSaver教程|聚合资源搜索并实现远程访问
运维·服务器·网络·python·docker·容器·pandas
从零开始学习人工智能3 小时前
WSL2部署CUDA12+cuDNN9踩坑实录:ONNX Runtime GPU推理环境搭建全流程
python
m0_380743873 小时前
从零调用 Claude 教程
开发语言·python·node.js
min(a,b)5 小时前
学习第17天:Agent Memory 与 MCP 协议
python·学习
CodeBlog-star5 小时前
LLM安全实战:提示词注入与越狱攻击防御指南
python·agent·提示词攻击·越狱攻击
小柯南敲键盘6 小时前
电商图片翻译工具推荐,批量处理主图视频字幕,免费试用
大数据·人工智能·python·音视频
比高创意品牌策划设计6 小时前
零售卖场设计软件用CAD还是SketchUp还是酷家乐
python
迷迭香yy8 小时前
行业板块轮动因子实战从板块资金到因子建模的本地化Python全流程
数据库·人工智能·python
W_326008 小时前
Python文件进阶:一维数据与 CSV 文件读写
开发语言·python