Python之系统交互(调用系统命令)subprocess

在早期的Python版本中,我们主要是通过os.system()、os.popen().read()等函数来执行命令行指令的,另外还有一个很少使用的commands模块。但是从Python 2.4开始官方文档中建议使用的是subprocess模块。(本文的例子全部是以Python3.5为运行环境)

对于调用一个系统命令,我们最关心的有如下几点:

 命令执行的状态码–表示命令执行是否成功

命令执行的输出结果–命令执行成功后或者错误后的输出

接下来,我们分别看下这几种方法。

 一、os.system()和os.popen()的用法 我们先来看下os.system()的用法:

我们先来看下os.system()的用法:


Python之系统交互(调用系统命令)subprocess_第1张图片

输出结果如下


Python之系统交互(调用系统命令)subprocess_第2张图片

结论:os.system(command)会返回命令执行的返回码,而将命令执行结果输出到屏幕。

os.popen()的代码如下


输出结果如下


Python之系统交互(调用系统命令)subprocess_第3张图片

结论:os.popen(command).read()可以获取命令执行结果,但是无法获取命令执行的返回码。

这两个命令,都功能不全呢?有没有既能拿到返回码,又能拿到输出结果的呢?有。

二、subprocess.run的用法

 subprocess是Python 2.4中新增的一个模块,它允许你生成新的进程,连接到它们的 input/output/error 管道,并获取它们的返回(状态)码。 在Python 3.5之后的版本中,官方文档中提倡通过subprocess.run()函数替代其他函数来使用subproccess模块的功能;

在Python 3.5之前的版本中,我们可以通过subprocess.call(),subprocess.getoutput()等上面列出的其他函数来使用subprocess模块的功能;


Python之系统交互(调用系统命令)subprocess_第4张图片

输出结果如下



subprocess.run()返回了一个类,其中包含了程序运行返回码,和输出内容。 注意:如果加上了check=True参数,表示命令执行失败会抛出异常。

2.1 关于输出

 我们可以看到,上面输出的结果是 b’xxxxx’,这是一个bytes类型的数据。实际使用中需要将其转换为字符串格式。


2.2 输出到HTML时保留换行

 默认情况下,将带有换行的数据字符串输出到HTML中,字符串会变成一行,没有换行,如果想保留原字符串的换行格式,需要使用HTML标签

例如


2.3 关于shell参数

 shell默认为False。

在Linux下,shell=False时, 如果args是字符串,那么只能是命令,不能包含任何参数,否则报错;如果args是一个列表list,则args的第一项是定义程序命令字符串,其它项是调用系统Shell时的附加参数。

shell=True时,如果args是字符串,Popen直接调用系统的Shell来执行,字符串格式和shell终端书写格式一样;如果args是一个列表list,则args的第一项是定义程序命令字符串,其它项是调用系统Shell时的附加参数。官方推荐shell=True时,使用字符串方式传递参数。

如果想使用shell中的管道,重定向,文件通配符,环境变量等功能,例如”ifconfig |grep eth0 > mm”,那么只能使用shell=True,并且使用字符串来传递。

综上,shell=True功能最强大的,但因为强大也存在安全风险,需要谨慎的对待传递的参数。

2.4 关于超时

很多脚本运行时会卡住,导致调用脚本一直等待,这很显然不是我们想看到的,因此执行命令的超时Timeout设置很有必要。好在subprocess.run()提供了timeout参数,使用如下:


如果在30秒内无法执行完毕,会爆出异常。


我们也可以使用try、except捕捉这个异常


Python之系统交互(调用系统命令)subprocess_第5张图片

三、subprocess.call和subprocess.getoutput用法


Python之系统交互(调用系统命令)subprocess_第6张图片

显示结果:


Python之系统交互(调用系统命令)subprocess_第7张图片

subprocess.call()只能返回状态码。subprocess.getoutput(cmd)只能输出命令结果。

 四、subprocess.popen()的使用


 实际上,上面的几个函数都是基于Popen()的封装(wrapper)。这些封装的目的在于让我们容易使用子进程。当我们想要更个性化我们的需求的时候,就要转向Popen类,该类生成的对象用来代表子进程。


Python之系统交互(调用系统命令)subprocess_第8张图片

执行结果如下:


Python之系统交互(调用系统命令)subprocess_第9张图片

你可能感兴趣的:(Python之系统交互(调用系统命令)subprocess)