作者 | 陈祥安
来源 | Python学习开发(ID:python3-5)
【导读】Subprocess 模块有什么用?有些时候需要调用系统内部的一些命令,或者给某个应用命令传不定参数时可以使用该模块。今天,这篇文章将带领大家认识 Subprocess 模块和基本使用方法。
初识 Subprocess 模块
Subprocess 模块提供了多个方法来运行额外的进程。在 Python2.7 的时候使用的方法主要有 call(),check_call(), check_output(),到了 Python3.5 的时候加入了一个更高级的方法 run(),该方法可以运行一个额外的进程同时它还能收集到运行之后的结果。Popen 类最为一个低级 API,它主要用于构建其他 API,在更复杂的流程交互中非常有用。Popen 的构造函数接受参数来设置新进程,以便父进程可以通过管道与它通信。它替换了其他模块和函数的所有功能,甚至更多。Subprocess 子进程模块旨在替换 os.system(), os.spawnv()等函数,os 和 popen2 模块中 popen()的变体,以及 commands()模块。
注意:在 Unix 和 Windows 系统上工作的应用编程接口大致相同,但是底层的实现是不同的,因为操作系统中的过程模型不同。这里显示的所有示例都是在 Mac 操作系统上测试的。在非 Unix 操作系统上的行为可能会有所不同。例如 unix 系统查看文件列表使用 ls,windows 只能使用 dir.
Run 方法使用
运行外部命令
要实现和 os.system()命令相同的方式,运行外部命令而不与之交互时候,我们可以使用 run()函数。前面提到了这是一个高级函数,先看一下其语法结构。
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, capture_output=False, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None, text=None, env=None, universal_newlines=None)
运行被 arg 描述的指令。等待指令完成,然后返回一个 CompletedProcess 示例。run 方法的参数和 Popen 的构造函数一样,接受的大多数参数都被传递给该接口。(timeout, input, check 和 capture_output 除外)。
import subprocess
completed = subprocess.run(['ls', '-1'])
print('returncode:', completed.returncode)
输出内容:
subprocess_demo.py
returncode: 0
第一个参数传入的就是我们要运行的命令,其格式推荐使用列表字符串的形式,将命令进行分割。这避免了转义引号或 shell 可能解释的其他特殊字符的需要。
如果将 shell 参数设置为 true 值将导致子进程生成一个中间 shell 进程,然后运行该命令。默认情况下是直接运行命令。
import subprocess
completed = subprocess.run('echo $HOME', shell=True)
print('returncode:', completed.returncode)
输出
/Users/chenxiangan
returncode: 0
使用中间 shell 意味着在运行命令之前要处理命令字符串中的变量、glob 模式和其他特殊的 shell 特性。
错误处理
CompletedProcess 的 returncode 属性是程序的退出代码。调用者负责解释它以检测错误。如果 run()的 check 参数为 True,则检查退出代码,如果它指示发生错误,则引发 CalledProcessError 异常。
import subprocess
try:
subprocess.run(['false'], check=True)
except subprocess.CalledProcessError as err:
print('ERROR:', err)
运行结果
ERROR: Command '['false']' returned non-zero exit status 1.
false 命令总是以非零状态代码退出,run()将其解释为错误。
将 run()函数的 check 属性设置为 True,等同于使用 check_call()方法。
获取结果
由于 run()启动的进程的标准输入和输出通道绑定到父输入和输出。这意味着调用程序无法捕获命令的输出。可以通过调整 stdout 和 stderr 参数来捕获输出的值。
import subprocess
completed = subprocess.run(
['ls', '-1'],
stdout=subprocess.PIPE,
)
print('returncode:', completed.returncode)
print(f"结果的字节长度 {len(completed.stdout)}:\n{ completed.stdout.decode('utf-8')}")
输出
returncode: 0结果的字节长度 24:subprocess_demo.py
ls -1命令成功运行,捕获并返回输出结果。
下一个示例在子 shell 中运行一系列命令。
在命令退出并显示错误代码之前,消息将发送到标准输出和标准错误。
import subprocess
try:
completed = subprocess.run(
'echo to stdout; echo to stderr 1>&2; e