GoDm@'s Blog

大蟒蛇subprocess模块极简入门

版权信息

warning

本文章为博主原创文章。遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。


写 Python 脚本时,经常会需要在 Python 代码里悄悄跑一个终端命令(比如跑一段 bash 脚本)。
那就不得不提到 Python 官方推荐的现代解决方案:subprocess 模块。由于我只是偶尔写点小脚本,只要掌握其中的一个函数就足够了,在此记录以防忘记。

唯一真神:subprocess.run()

自 Python 3.5 起,官方强烈建议使用 subprocess.run() 来替代其他老旧的函数。它的逻辑非常直白:运行指定的命令,等待它完成,然后返回一个包含执行结果的对象。

我们需要先导入它:

import subprocess

下面我们通过三个最常见的场景,来看看它到底怎么用。

场景一:只管执行,不需要获取输出 (Fire and Forget)

假设你只想在脚本里新建一个文件夹,不需要关心终端打印了什么。

import subprocess

# 执行命令: mkdir new_folder
subprocess.run(["mkdir", "new_folder"])

print("文件夹创建完毕!")

我们把命令写成了一个列表 ["mkdir", "new_folder"],而不是一个长字符串 "mkdir new_folder"。 这是 subprocess 的推荐写法,它可以有效避免复杂的空格转义和安全漏洞(比如 Shell 注入)。第一个元素是命令,后面的元素是参数。

场景二:我需要拿到命令的输出内容

这是写脚本时最常见的需求。比如你想用 Python 获取当前的系统时间或者某个配置项的值,你需要把终端打印的字存到 Python 的变量里。

import subprocess

# 运行 echo 命令,并捕获输出
result = subprocess.run(["echo", "Hello from terminal!"], capture_output=True, text=True)

# 打印获取到的内容
print(f"终端说: {result.stdout}")

核心要点: 这里加了两个非常关键的参数:

  1. capture_output=True:告诉 Python,不要把结果打印到屏幕上,而是偷偷拦截下来存进 result 对象里。

  2. text=True:告诉 Python 将输出结果作为普通的 字符串(String) 处理。如果不加这个参数,你得到的是带有 b'...' 前缀的字节流(Bytes),处理起来会很麻烦。

场景三:如果命令执行失败了怎么办?

写脚本最怕的就是静默失败。如果外部命令报错了,Python 脚本默认还会继续往下跑,这可能会导致灾难性的后果。

subprocess.run() 返回的 result 对象里,有一个叫 returncode 的属性。returncode == 0 代表成功,非 0 代表出错。

温和的处理方式(手动检查):

import subprocess

result = subprocess.run(["ls", "/nonexistent_folder"], capture_output=True, text=True)

if result.returncode == 0:
    print("命令执行成功!")
else:
    print(f"糟糕,出错了!错误代码: {result.returncode}")
    print(f"错误信息: {result.stderr}") # 报错信息通常存放在 stderr 中

暴力的处理方式(直接让脚本崩溃报错):

如果你希望外部命令一旦失败,Python 脚本就立刻停止并抛出异常,只需加一个 check=True 参数:

import subprocess

# 如果这个命令失败,Python 会直接抛出 CalledProcessError 异常
subprocess.run(["ls", "/nonexistent_folder"], check=True)

总结

如果偶尔写写脚本,把下面这段代码存成代码片段(Snippet),遇到需要调用外部命令的时候直接复制粘贴修改即可:

import subprocess

def run_command(cmd_list):
    """
    运行外部命令的通用模板
    """
    try:
        # capture_output 捕获输出, text=True 返回字符串, check=True 失败时抛出异常
        result = subprocess.run(cmd_list, capture_output=True, text=True, check=True)
        return result.stdout.strip() # strip() 用来去掉结尾多余的换行符
    except subprocess.CalledProcessError as e:
        print(f"命令执行失败: {e}")
        print(f"错误输出: {e.stderr}")
        return None

# 使用示例:
output = run_command(["git", "branch"])
if output:
    print(f"当前分支信息:\n{output}")

这就够用了!至于更复杂的管道符(|)交互或者后台异步执行,那是subprocess.Popen 的工作,等到真的需要写复杂的系统脚本时再去了解它也不迟。


共计约1.1k字。于2026/03/12首次发布,最后更新于2026/03/12。

本文章为博主原创文章。遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。

  1. 唯一真神:subprocess.run()
  2. 场景一:只管执行,不需要获取输出 (Fire and Forget)
  3. 场景二:我需要拿到命令的输出内容
  4. 场景三:如果命令执行失败了怎么办?
  5. 总结