Hero image home@2x

Python subprocess用法详解及常见示例

Python subprocess用法详解及常见示例

Python subprocess用法

Python 的 subprocess 模块用于生成新进程,连接到它们的输入和输出,以及获取它们的返回码。它可以替代许多其他模块,比如 os.system, os.spawn, os.popen等,提供了更灵活的接口和功能。

任务概述

本文将详细讲解如何使用 subprocess 模块执行外部命令,捕获输出,以及处理异常。我们将通过多个示例展示各种用法,解析每个功能,并提供注意事项和实用技巧。

基本概念

  • 创建子进程: 使用 subprocess,可以轻松创建和管理子进程。
  • 执行命令: 可以执行任何 shell 命令,并捕获其输出。
  • 两个重要的函数: subprocess.run()subprocess.Popen()

subprocess.run() 函数

subprocess.run() 是 Python 3.5 引入的函数,它简化了创建子进程并等待其完成的过程。

基本用法

执行基本命令的示例:

import subprocess

result = subprocess.run(['ls', '-l'], capture_output=True, text=True)

print(result.stdout)

在上述示例中:

  • 我们调用了 ls -l 命令。
  • capture_output=True 表示捕获标准输出和标准错误。
  • text=True 表示输出为字符串而不是字节。
  • 输出结果通过 result.stdout 获取。

处理返回码

返回码可以通过 result.returncode 来访问,0 表示执行成功,其他值表示失败。

if result.returncode == 0:

print("Command executed successfully")

else:

print(f"Error occurred: {result.returncode}")

subprocess.Popen() 函数

subprocess.Popen() 提供了更底层的接口,允许对进程的输入、输出和错误流进行更复杂的控制。

创建一个新的子进程

process = subprocess.Popen(['ping', '127.0.0.1'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

stdout, stderr = process.communicate()

print(stdout.decode())

在这个例子中:

  • 我们执行了 ping 127.0.0.1 命令。
  • 使用 subprocess.PIPE 来捕获输出。
  • process.communicate() 方法将阻塞,直到进程完成并返回输出。

异步处理

我们也可以启动一个进程而不等待它完成:

process = subprocess.Popen(['sleep', '5'])

print("Process started")

在这个示例中,程序不会阻塞,而是立即返回。

常见参数

  • args: 要执行的命令和参数列表。
  • stdin, stdout, stderr: 定义子进程的输入、输出和错误流。
  • cwd: 设置子进程的当前工作目录。
  • shell: 如果为 True,则命令将通过 shell 执行。

设置工作目录

subprocess.run(['ls', '-l'], cwd='/home/user')

上面的命令会在 /home/user 目录下执行 ls -l

在 shell 中执行命令

subprocess.run('echo $HOME', shell=True)

使用 shell=True 可以直接传入字符串形式的命令。

错误处理

在使用 subprocess 时,可能会遇到各种错误情况,例如命令未找到、权限不足等。可以通过检查异常来处理这些问题。

使用 try-except 捕获异常

try:

subprocess.run(['nonexistent_command'], check=True)

except subprocess.CalledProcessError as e:

print(f'Error: {e}')

在上述代码中,使用 check=True 参数可以确保在命令失败时抛出异常。

注意事项

  • 确保命令和参数的正确性,避免因拼写错误引起的问题。
  • 使用 shell=True 时要小心,避免命令注入的风险。
  • 在处理大型输出时,小心管道缓冲区的大小,适当使用 communicate()

实用技巧

  • 并发执行命令:可以使用 threadingmultiprocessing 模块与 subprocess 结合。
  • import threading

    def run_command(cmd):

    subprocess.run(cmd)

    threads = []

    for cmd in [['ls', '-l'], ['pwd']]:

    t = threading.Thread(target=run_command, args=(cmd,))

    threads.append(t)

    t.start()

    for t in threads:

    t.join()

  • 实时输出:使用 stdout=subprocess.PIPEcommunicate() 的结合,可以实现实时输出。
  • process = subprocess.Popen(['ping', '127.0.0.1'], stdout=subprocess.PIPE)

    for line in iter(process.stdout.readline, b''):

    print(line.decode().strip())

总结

subprocess 模块强大且灵活,它能够帮助我们轻松地运行外部命令和管理进程。通过掌握其基本用法及相关参数设置,不仅能够提高 Python 程序的功能性,也能增强用户与系统的交互能力。希望本文对你在使用 subprocess 模块时提供了帮助与启发。