您的位置:

Python subprocess模块应用详解

前言

Python作为一门脚本语言,由于其简单易学,方便快捷的特点,逐渐成为了当今最受欢迎的编程语言之一。在实际应用中,我们常常会用Python编写一些与操作系统交互的脚本,例如自动化操作、系统管理以及数据分析等方面。而对于许多需要与操作系统直接交互的任务,我们通常会使用Python标准库中的subprocess模块。

什么是subprocess模块

subprocess模块是Python标准库中用于创建新进程的模块,它允许我们启动一个新进程执行其他程序,并与其交互。可以说,在Python中使用subprocess模块可以非常方便地执行系统命令、调用其他程序,以及实现数据流的输入和输出。

常见子进程的使用

在使用Python subprocess模块的过程中,我们通常涉及到以下几种常见的子进程:

1. Popen

Popen是subprocess模块中最核心的函数。当需要创建一个新进程时,我们通常会使用此函数。它的语法如下所示:

subprocess.Popen(args, bufsize=0, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=(), *, encoding=None, errors=None)

其中各个参数含义如下:

  • args: 需要执行的程序或命令,字符串形式,例如:'ls -l'。
  • bufsize: 缓存区大小,默认为0,表示使用操作系统默认值。
  • executable: 可执行文件的路径,如果未提供,则默认使用 args 参数第一个空格前的字符串。
  • stdin/stdout/stderr: 分别为标准输入、标准输出和标准错误输出的文件描述符。如果没有设置,则默认使用父进程的相应文件描述符。
  • preexec_fn: 在子进程运行之前调用的可执行对象(callable),只能在UNIX平台使用。
  • close_fds: 是否在子进程中关闭所有父进程中打开的文件描述符。默认为True。
  • shell: 布尔值,表示是否使用shell执行命令。默认为False。
  • cwd: 子进程的当前工作目录。
  • env: 子进程的环境变量。
  • universal_newlines: 布尔值,是否将输入输出流中的\r和\n转换成\n。默认为False。
  • startupinfo: 传递一个对象,其中包含指定如何创建子进程的 Windows 特定信息。
  • creationflags: 指定附加的创建标志。只在Windows中有用。
  • pass_fds: 要传递给子进程的文件描述符序列。
  • encoding, errors:如果相关参数已启用,则可以传递编码与解码错误信息

2. call, check_call, check_output

除了Popen函数外,subprocess模块还提供了一些更多高级用法的函数。其中call函数是最简单的函数,它与Popen函数很相似,但通过返回值来确定进程是否已退出,以及进程的退出状态。

check_call函数和check_output函数都是基于call函数的封装。

3. run

Python 3.5中新增加的run函数,通过它可以更加方便地执行命令

子进程执行命令的基本用法

import subprocess

# 执行“ls /tmp”命令
subprocess.run(['ls', '/tmp'])

# 执行“echo 'Hello World'”命令,并将执行结果输出到标准输出
result = subprocess.run(['echo', 'Hello World'], stdout=subprocess.PIPE)
print(result.stdout)

子进程和主进程之间的交互

使用subprocess模块创建子进程时,主进程和子进程之间可以通过管道进行通信。通过pipe参数可以指定标准输入、标注输出和标准错误输出使用的管道。

import subprocess

# 创建子进程执行“cat”命令,并将标准输入和标准输出连接到管道
p = subprocess.Popen(['cat'], stdin=subprocess.PIPE, stdout=subprocess.PIPE)

# 向子进程写入数据
p.stdin.write(b'hello\n')

# 从子进程读取输出
print(p.stdout.readline().decode())

使用Shell命令

当将shell参数设置为True时,subprocess模块将默认使用shell执行命令。在下面的例子中,我们执行“ls -l /tmp”命令,使用管道将其转输到“grep test”命令中进行过滤,并输出结果。

import subprocess

# 使用shell执行命令
p = subprocess.Popen('ls -l /tmp | grep test', shell=True, stdout=subprocess.PIPE)

# 读取输出
output = p.stdout.read().decode()

# 输出结果
print(output)