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。

笔记加载中…