← 返回题目列表

Python subprocess 和 multiprocessing 有什么区别?什么时候用哪个?

高频 中等 第 11 / 27 题 更新于 2026/07/31
subprocessmultiprocessing进程外部命令

简化版

subprocess 用来启动和控制外部程序,例如执行 ffmpeggit、系统命令;multiprocessing 用来在 Python 中创建子进程并运行 Python 函数,常用于绕过 GIL 做 CPU 密集计算。前者关注外部命令,后者关注 Python 任务并行。

详细版

如果你要调用现成命令行工具,用 subprocess.run()Popen();如果你要把 Python 函数分发到多个进程执行,用 multiprocessing.ProcessPoolProcessPoolExecutor

import subprocess
subprocess.run(["git", "status"], check=True)
from multiprocessing import Pool
with Pool() as pool:
    print(pool.map(cpu_work, range(10)))

安全上,subprocess 要避免 shell=True 拼接用户输入;性能上,multiprocessing 有序列化和进程通信成本,不适合很小的任务。

完整版教学

一、两个模块解决的问题不同

subprocess 是“从 Python 调外部程序”。外部程序可以是任何可执行文件,不一定是 Python。multiprocessing 是“用多个 Python 进程跑 Python 代码”。它们都创建进程,但抽象层不同。

subprocess:
Python -> ffmpeg/git/curl

multiprocessing:
Python parent -> Python child -> run function

这一区分是面试回答的主线。

二、subprocess 适合什么场景

调用系统工具、脚本、编译器、压缩工具、媒体处理工具时用 subprocess。它能控制参数、环境变量、工作目录、标准输入输出和退出码。

result = subprocess.run(
    ["python", "--version"],
    capture_output=True,
    text=True,
    check=True,
)
print(result.stdout)

如果命令失败,check=True 会抛异常。生产中要记录命令、退出码、stderr,并设置超时,避免外部命令卡死。

三、multiprocessing 适合什么场景

CPU 密集型 Python 函数可以用多进程并行,因为每个进程有自己的解释器和 GIL。例如图像处理、压缩、特征计算、批量数据转换。

from concurrent.futures import ProcessPoolExecutor

with ProcessPoolExecutor() as ex:
    results = list(ex.map(parse_file, files))

但任务参数和结果需要 pickle 序列化,进程启动也有成本。100 万个 1ms 小任务直接丢进进程池,调度和序列化成本可能超过计算本身。

四、shell=True 为什么危险

subprocess.run("rm -rf " + user_input, shell=True) 这类拼接很危险。用户输入可能注入额外命令。更安全做法是传参数列表,并避免 shell 解释。

subprocess.run(["grep", pattern, filename], check=True)
写法风险
字符串拼接 + shell=True命令注入
参数列表 + shell=False更安全
固定命令 + 校验参数推荐

调外部命令时,用户输入必须当“参数”传,不要当“命令文本”拼。

五、输出和超时怎么处理

外部命令可能输出很多内容。如果使用 Popen 但不消费 stdout/stderr,管道缓冲区可能被写满,导致子进程阻塞。简单场景用 subprocess.run(capture_output=True, timeout=...)

subprocess.run(
    ["tool", "arg"],
    timeout=30,
    capture_output=True,
    text=True,
)

长时间运行的命令要流式读取日志,或者让它直接输出到文件/平台日志,避免一次性把几百 MB 输出读进内存。

六、怎么做选择

如果已有成熟命令行工具,subprocess 通常最直接;如果核心逻辑是 Python 函数,且需要 CPU 并行,选 multiprocessingProcessPoolExecutor

场景选择
ffmpeg 转码subprocess
git 查询状态subprocess
并行计算图片特征multiprocessing
并行解析 Python 对象ProcessPoolExecutor

还要考虑部署环境:外部命令必须存在于机器或镜像中;多进程则要考虑启动方式、pickle、内存占用。

七、常见误区与追问

  • 误区:subprocess 和 multiprocessing 是一回事。 都会创建进程,但一个调外部程序,一个跑 Python 函数。
  • 误区:shell=True 更方便所以推荐。 它有命令注入风险,默认应避免。
  • 误区:多进程一定更快。 序列化、进程启动和 IPC 都有成本,小任务可能更慢。
  • 追问:如何拿到外部命令输出? capture_output=TruePopen 管道读取。
  • 追问:外部命令卡住怎么办? 设置 timeout,必要时终止进程树。
  • 追问:ProcessPool 传 lambda 可以吗? 通常不行,目标函数和参数要可 pickle。
  • 追问:调用外部命令如何传环境变量?env 参数传入明确环境。

八、加强记忆

subprocess 记成“调外部命令”,multiprocessing 记成“跑 Python 函数并行”。前者重点是参数安全、退出码、stdout/stderr、timeout;后者重点是 GIL、pickle、启动方式和任务粒度。先问“我要执行的是外部程序还是 Python 函数”,选择就清楚了。