Python3 subprocess 模块
在 Python 里调用系统外部命令(ls/dir、git、node、pip 等)并获取其输出,官方推荐用 subprocess 模块。它比旧的 os.system 更强大:能拿到返回码、捕获 stdout/stderr、设置超时,还更安全。
快速上手:subprocess.run
run() 接收"命令参数列表",运行命令并等待它结束:
import subprocess
r = subprocess.run(["python", "-c", "print('你好')"])
print("返回码:", r.returncode) # 输出:返回码: 0
捕获输出:capture_output 与 text
默认输出直接打到终端;要取回结果需加 capture_output=True,并用 text=True 让输出以字符串返回:
import subprocess
r = subprocess.run(["python", "-c", "print('内部输出')"],
capture_output=True, # 捕获 stdout 与 stderr
text=True) # 以文本而非字节返回
print(r.stdout) # 输出:内部输出
print(r.stderr) # 输出:(空,无错误输出)
若不写 text=True,stdout/stderr 是 bytes,可手动 r.stdout.decode("utf-8")。
返回码与常用参数
- returncode:0 表示成功,非 0 表示失败;设 check=True 时失败会直接抛 CalledProcessError;
- timeout=秒数:命令超时抛 TimeoutExpired;
import subprocess
try:
r = subprocess.run(["python", "-c", "import time; time.sleep(10)"],
timeout=3) # 3 秒未结束即中断并报错
except subprocess.TimeoutExpired:
print("命令执行超时") # 输出:命令执行超时
示例:执行 dir/ls 并读取结果
注意:Windows 的 dir 是 cmd 内建命令,需写成 ["cmd", "/c", "dir"] 才能运行:
import os
import subprocess
cmd = ["cmd", "/c", "dir"] if os.name == "nt" else ["ls", "-l"]
r = subprocess.run(cmd, capture_output=True, text=True)
print("返回码:", r.returncode) # 输出:返回码: 0
print(r.stdout) # 输出:目录清单(内容随环境而定)
Popen:更底层的控制
需要与子进程持续交互、实时读取输出时,用 Popen 配合 communicate():
import subprocess
p = subprocess.Popen(["python", "-c", "print('hello')"],
stdout=subprocess.PIPE, text=True)
out, err = p.communicate() # 等待结束并收集全部输出
print(p.returncode, out) # 输出:0 hello
安全提示:慎用 shell=True
默认传参数列表时不经过 shell,参数原样交给程序,最安全;一旦 shell=True 且拼接用户输入,就可能被注入恶意命令:
import subprocess
# 危险写法:shell=True 拼接用户输入,可能执行任意命令
# subprocess.run("ping " + user_input, shell=True)
# 安全写法:用参数列表,Python 负责拆分,不经过 shell 解析
subprocess.run(["ping", "127.0.0.1"]) # 参数永远不会被当作命令执行
小结:subprocess.run 是调用外部命令的标准入口——列表传参、capture_output/text 取结果、check/timeout 控制异常,复杂交互交给 Popen,并尽量避免 shell=True。