摘要:subprocess是 Python 中用于创建和管理子进程的核心模块,它取代了旧有的os.system和os.spawn*方法,提供了更灵活、安全的进程交互能力。以下是深入理解该模块的关键点:
subprocess 是 Python 中用于创建和管理子进程的核心模块,它取代了旧有的 os.system 和 os.spawn* 方法,提供了更灵活、安全的进程交互能力。以下是深入理解该模块的关键点:
1. 核心函数与类
subprocess.run(推荐)执行命令并等待完成,返回 CompletedProcess 对象。适合大多数场景。
python
result = subprocess.run(["ls", "-l"], capture_output=True, text=True)
print(result.stdout)
subprocess.Popen底层类,用于更复杂的流程控制(如异步交互、管道连接)。需手动管理输入/输出流。
2. 关键参数解析
args命令参数可以是列表(推荐)或字符串。使用列表避免 shell 注入风险。
python
# 安全方式(无 shell=True)
subprocess.run(["echo", "Hello; rm -rf /"]) # 分号不会被解析为命令
# 危险方式(shell=True 时需谨慎)
subprocess.run("echo Hello; rm -rf /", shell=True) # 分号会执行恶意命令
shell=True通过系统 shell 执行命令,支持通配符、管道等 shell 特性,但可能引发安全漏洞。仅在必要时使用。stdin/stdout/stderr
控制输入/输出流:subprocess.PIPE:捕获输出或传递输入。subprocess.DEVNULL:丢弃输出。文件对象:重定向到文件。text=True 或 encoding
以字符串形式处理输入输出(默认返回字节流)。timeout
设置超时(秒),超时抛出 TimeoutExpired 异常。
3. 输入输出交互
捕获输出
python
result = subprocess.run(
["ls", "-l"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True
)
print(result.stdout)
实时输出处理
通过 Popen 逐行读取:
python
proc = subprocess.Popen(["ping", "google.com"], stdout=subprocess.PIPE, text=True)
for line in proc.stdout:
print(line.strip)
传递输入
使用 communicate 发送输入:
python
proc = subprocess.Popen(
["grep", "hello"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
text=True
)
output, _ = proc.communicate("hello world\nhi there\n")
print(output) # 输出 "hello world"
4. 错误处理
检查返回码check=True 会在非零返回码时抛出 CalledProcessError:
python
try:
subprocess.run(["false"], check=True)
except subprocess.CalledProcessError as e:
print(f"Command failed: {e}")
处理超时python
try:
subprocess.run(["sleep", "10"], timeout=5)
except subprocess.TimeoutExpired:
print("Process timed out!")
5. 高级用法
管道链(Shell 管道模拟)
python
ps = subprocess.Popen(["ps", "-A"], stdout=subprocess.PIPE)
grep = subprocess.Popen(["grep", "python"], stdin=ps.stdout, stdout=subprocess.PIPE)
ps.stdout.close
output, _ = grep.communicate
环境变量控制
python
env = {"PATH": "/usr/local/bin"}
subprocess.run(["echo", "$PATH"], env=env, shell=True)
异步执行
python
proc = subprocess.Popen(["long_running_task"])
# 继续执行其他操作...
proc.wait # 等待完成
6. 安全注意事项
避免 shell=True + 不可信输入若必须使用,用 shlex.quote 转义参数。优先使用列表传参
防止参数分割错误(如文件名含空格)。限制资源使用
结合 resource 模块防止子进程耗尽资源。
7. 常见问题
为何 Popen 不立即输出?输出可能被缓冲,使用 flush=True 或 unbuffered 模式。如何处理交互式程序(如 ssh)?
使用 pexpect 库(专为交互设计)。
通过掌握这些概念,你可以高效、安全地利用 subprocess 实现进程管理、自动化脚本等复杂任务。
来源:老客数据一点号