Python 执行系统命令的三种方式与 subprocess 详解

Hazel
Hazel
发布时间:2026-10-11 | 5人浏览过
原创

在 Python 开发中,调用外部系统命令(如 Linux 的 ls、cp 或 Windows 的 dir)是常见需求。本文总结了三种执行命令的方法,并深入解析了功能最强大的 subprocess 模块,包括其核心类 Popen 的参数配置与进程交互机制。

执行系统命令的三种方法

Python 提供了多种调用外部程序的途径,根据对输出结果和进程控制的需求不同,主要可分为以下三类:

1. 使用 os.system

这是最简单直接的方式,适用于只需要执行命令且不需要获取返回结果或标准输出的场景。该方法会直接打印命令在终端的执行信息。

import os
os.system("ls")

2. 使用 commands 模块(仅限 Linux/Unix)

在 Linux 环境下,可以使用内置的 commands 模块。它提供了更高层级的封装,适合快速获取命令的状态码或输出内容。

import commands
# 获取状态码和输出
status, output = commands.getstatusoutput("ls")
# 仅获取输出
commands.getoutput("ls")
# 仅获取状态
commands.getstatus("ls")

3. 使用 subprocess 模块(推荐)

subprocess 模块是 Python 官方推荐的用于生成和管理新进程的模块。它提供了更细粒度的控制,允许开发者捕获标准输入、输出和错误流,并处理进程间的通信。使用前需导入:

from subprocess import Popen, PIPE

subprocess.Popen 核心参数解析

Popen 类是 subprocess 模块的核心,用于创建子进程。其构造函数包含大量参数,用于精确控制子进程的行为:

subprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=False, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0)

关键参数说明如下:

  • args: 要执行的命令或程序路径。
  • bufsize: 指定缓冲大小。
  • executable: 指定要执行的可执行程序。当 shell=True 时,此参数指定使用的 shell。
  • shell: 若为 True,则通过 shell 执行命令。Windows 下默认 shell 由 COMSPEC 环境变量指定。
  • stdin, stdout, stderr: 可设置为 PIPE、文件描述符或 None。使用 subprocess.PIPE 可初始化这些流以进行进程间通信。若将 stderr 初始化为 subprocess.STDOUT,则错误信息将通过标准输出流输出。
  • preexec_fn: 仅在 Unix 平台有效,指定在子进程执行前调用的对象。
  • close_fds: Windows 下若为 True,则不继承父进程管道。注意:不能将 close_fds 设为 True 同时重定向标准输入、输出或错误流。
  • cwd: 用于设置子进程的当前工作目录。
  • env: 字典类型,指定子进程的环境变量;若为 None,则继承父进程环境。
  • universal_newlines: 若为 True,统一将换行符当作 /n 处理。
  • startupinfo 与 creationflags: 仅在 Windows 下有效,用于控制进程创建标志。

Popen 对象的方法与属性

创建 Popen 实例后,可通过其属性和方法监控和控制子进程:

常用属性

  • pid: 获取子进程的进程 ID。
  • returncode: 获取进程返回值。若进程尚未结束,返回 None。
  • stdin, stdout, stderr: 返回文件对象,用于发送或读取指令。若未设置为 PIPE,则为 None。

常用方法

  • poll(): 检查子进程是否结束,并返回 returncode。
  • wait(): 等待子进程结束,并返回 returncode。注意:这是一个阻塞方法,若命令内容较多或产生大量输出,可能导致主程序阻塞。
  • communicate(input=None): 与子进程交互,可选 input 指定发送参数。该方法返回一个元组 (stdoutdata, stderrdata),是获取命令输出和错误信息的推荐方式。
  • send_signal(signal): 向子进程发送信号。
  • terminate(): 停止子进程。在 Windows 下调用 TerminateProcess()。
  • kill(): 杀死子进程。

实战示例:执行命令并处理返回值

以下示例展示了如何使用 Popen 执行复制命令,并通过 PIPE 捕获输出和错误,最后检查返回值以判断执行是否成功。

p = Popen("cp -rf a/* b/", shell=True, stdout=PIPE, stderr=PIPE)
p.wait()
if p.returncode != 0: 
    print "Error."
    return -1

在此示例中:

  1. 通过 stdout=PIPE, stderr=PIPE 初始化标准输出和错误流,以便后续读取。
  2. 调用 p.wait() 阻塞等待进程结束。
  3. 检查 p.returncode,非 0 表示执行出错。

注意事项与排错

  • 阻塞问题:Popen 默认是阻塞的。如果不使用 wait() 或 communicate(),虽然避免了阻塞,但无法获取返回值和输出。对于长时间运行的命令,建议使用 communicate() 以避免死锁。
  • 平台差异:部分参数(如 preexec_fn)仅在 Unix 平台有效,Windows 下使用需注意兼容性问题。
  • 管道重限制:在 Windows 下,若 close_fds=True,则不能同时重定向标准输入、输出或错误流,否则会导致异常。

以上就是对 Python 中执行系统命令的三种方法及 subprocess 模块详细用法的总结,更多关于 Python 进程管理的资料请关注本站其它相关文章!

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表