前言
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)