subprocess
是 Python 中用于创建和管理子进程的标准库模块,可执行外部命令、获取输出、管理输入/输出流及错误流。以下是核心用法详解:
subprocess.run()
(推荐)import subprocess
# 执行命令并等待完成(返回 CompletedProcess 对象)
result = subprocess.run(["ls", "-l"], capture_output=True, text=True)
print("返回码:", result.returncode) # 0 表示成功
print("标准输出:", result.stdout)
print("错误输出:", result.stderr)
关键参数:
args
:命令列表(推荐)或字符串(需 shell=True
)capture_output=True
:捕获输出(相当于设置 stdout=subprocess.PIPE, stderr=subprocess.PIPE
)text=True
:以字符串形式返回输出(默认返回字节)check=True
:返回码非零时抛出 CalledProcessError
异常subprocess.Popen()
用于异步执行或复杂交互:
# 启动进程
process = subprocess.Popen(
["ping", "google.com"],
stdout=subprocess.PIPE,
text=True
)
# 逐行读取输出
while True:
line = process.stdout.readline()
if not line:
break
print(line.strip())
# 等待进程结束
return_code = process.wait()
print("返回码:", return_code)
向子进程传递输入:
# 执行 grep 并传递输入文本
result = subprocess.run(
["grep", "python"],
input="hello\npython\nworld", # 输入数据
text=True,
capture_output=True
)
print(result.stdout) # 输出: "python"
try:
subprocess.run(["invalid_cmd"], check=True, capture_output=True, text=True)
except subprocess.CalledProcessError as e:
print(f"命令失败!返回码: {e.returncode}")
print(f"错误输出: {e.stderr}")
try:
subprocess.run(["sleep", "10"], timeout=5) # 5秒后终止进程
except subprocess.TimeoutExpired:
print("命令执行超时!")
shell=True
:除非必要(如执行 shell 内置命令),否则使用命令列表形式防止注入攻击:# 危险!用户输入可能执行恶意命令
user_input = "malicious_command; rm -rf /"
subprocess.run(f"echo {user_input}", shell=True) # 风险!
# 安全方式(使用列表)
subprocess.run(["echo", user_input]) # user_input 作为普通参数
output = subprocess.check_output(["date", "+%Y-%m-%d"], text=True)
print("当前日期:", output.strip())
result = subprocess.run(
["ls", "/nonexistent"],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT, # 将错误流合并到标准输出
text=True
)
print("合并输出:", result.stdout)
# 启动后台进程(不等待)
subprocess.Popen(["notepad.exe"])
print("主程序继续执行...")
os.path.join
代替硬编码的 /
或 \
dir
vs ls
),可用 sys.platform
做判断:import sys
cmd = ["dir"] if sys.platform.startswith("win") else ["ls", "-l"]
场景 | 推荐方法 |
---|---|
简单命令同步执行 | subprocess.run() |
实时流式处理输出 | subprocess.Popen() + 循环读取 |
需要输入交互 | input= 参数 |
严格错误处理 | check=True + 异常捕获 |
超时控制 | timeout= 参数 |