python获取系统进程 获取python的运行结果_命令行

上一篇文章已经介绍了python如何调用linux命令行执行命令,本文将主要介绍如何在python脚本中获取linux命令行命令的输出(与上一篇文章所提到的模块几乎是相同的)。

linux是系统,而python则只是一种编程语言,很多时候需要使用到linux的命令行来执行某些功能或者运行某些软件。而有时候我们需要知道软件执行的成功与否或者需要获取命令在命令行中的输出,这些输出可能会作为python中的新变量。上面描述的情况对我来说是比较常见的,因此我将简要介绍如何在python中获取linux命令行在终端的输出内容。

常见的使用python获取linux shell命令行命令的执行结果的方式大致有使用os模块和subprocess模块两种方式。


文章目录

  • os模块
  • subprocess模块
  • subprocess.run()
  • subprocess.call()
  • subprocess.Popen()
  • subprocess.check_output()
  • subprocess.getstatusoutput()



os模块

首先要介绍的还是更为常用的os模块,上一篇文章讲过os.system()和os.popen()都能够调用命令行执行命令,但os.system()的返回值为命令退出状态码,os.popen()得到的返回值则是文件对象,可以使用例如read()、readline()、readlines()等命令进行读取。

例:

os.system

>>> import os

>>> a = os.system('ls | wc -l')
15   # 运行命令的结果,由于在终端,因此直接打印出来了,获取命令行的输出有时候就是获取15这样的内容。
>>> print(a)
0    # 退出状态码,为0时是正常执行。

>>> b = os.system('lsk')   # 这里随便输了一个错误的命令
sh: 1: lsk: not found      # 终端显示没有这个命令,也可以看出这时候使用的shell为sh
>>> print(b)              
32512  # 退出状态码为32512,应该是一个代表发生错误的状态码

os.popen

>>> import os
>>> a = os.popen('ls')
>>> print(a.readlines())
['bin\n', 'etc\n', 'ete3\n', 'include\n', 'lib\n', 'share\n']
# 得到的结果为文件对象,使用readlines()将其变为列表,
# 之后可以将这些内容用于python后续的操作。
>>> b = os.popen('lsk')     
>>> /bin/sh: 1: lsk: not found       # 提示命令出错

>>> print(b.read())
# 未输出结果,表明错误信息不会被python捕捉

subprocess模块

subprocess译为子进程,这个模块现在才是王者级的存在,其功能很丰富,上篇文章也提到了subprocess模块的各种方法如run、call、Popen、check_output等使用方式类似,最主要的区别在于它们的返回值不同。接下来将介绍每种方法的返回值。

subprocess.run()

此方法上篇文章已介绍过,其返回值为一个CompletedProcess的类实例,这个类实例返回时会带上返回的状态和最开始传入的参数。直接拷贝上篇文章的内容:

>>> import subprocess

>>> a = subprocess.run('ls -h -a', shell = True)
.  ..  bin  etc  ete3  include	lib  share
# ls -h -a查看当前目录下的所有文件及文件夹
# 这里如果shell为False会报错

>>> print(a)
CompletedProcess(args='ls -h -a', returncode=0)
# 运行结果a为类实例,可以看到返回状态和参数

subprocess.call()

subprocess.call()与os.system()类似,两个方法都是返回命令执行的退出状态,subprocess.call()执行的效果:

>>> import subprocess
>>> a = subprocess.call('ls')
bin  etc  ete3	include  lib  share
>>> print(a)
0
# 成功运行的退出码

>>> b = subprocess.call('lsk', shell=True)
/bin/sh: 1: lsk: not found
# 这里需要使用到shell=True调用shell,否则会报错而直接停止运行。
>>> print(b)
127
# 错误运行的退出码

在某些情况下可能会使用到这些退出码来判断命令是否正常运行了。

subprocess.Popen()

Popen为subprocess类底层调用的方法,Popen类还支持很多的方法如Popen.wait()、Popen.poll()、communicate()、Popen.terminate()等很多的方法,还可以通过如Popen.args、Popen.stdin、Popen.stdout、Popen.stderr等查看某些参数、管道内容或者某些输出,因此使用灵活性更强。

看一个使用Popen的简单的例子吧:

>>> import subprocess

>>> a = subprocess.Popen('ls', stdout = subprocess.PIPE, stderr = subprocess.PIPE)
# 这里将输出和错误和都交给subprocess的管道
>>> print(a)
<subprocess.Popen object at 0x7f3a19987940>
# 得到的返回值a为一个Popen类的类实例
>>> a.communicate()
(b'bin\netc\nete3\ninclude\nlib\nshare\n', b'')
# 通过communicate方法获取输出(标准输出和错误),得到了一个元组,其中的元素都是二进制形式的
# 第一个元素为标准输出,第二个元素为错误信息
>>> a.communicate()[0].decode() 
'bin\netc\nete3\ninclude\nlib\nshare\n'
# 使用decode方法对二进制结果进行解码,得到的为ls的结果(虽说混到了一起)
>>> a.communicate()[1].decode()
''
# 对标准错误进行解码无结果,这是因为命令正确执行了并未出错

subprocess.check_output()

这个命令看名字就清楚了,它就是获取命令行命令执行结果的一条很明显的命令,其使用方式也与上面几乎相同,但其得到的结果也是二进制形式,需要通过decode进行解码。

>>> import subprocess

>>> a = subprocess.check_output('ls')
>>> print(a)
b'bin\netc\nete3\ninclude\nlib\nshare\n'
>>> a.decode()
'bin\netc\nete3\ninclude\nlib\nshare\n'
# 不多解释

subprocess.getstatusoutput()

这个命令返回值为退出状态码和标准输出组成的元组,即(exitcode, output)。

>>> import subprocess

>>> a = subprocess.getstatusoutput('ls')
>>> a
(0, 'bin\netc\nete3\ninclude\nlib\nshare')
>>> a[1]
'bin\netc\nete3\ninclude\nlib\nshare'
# 不多解释

本文已介绍平常可能会用上的subprocess方法,还有一些其它的方法可能不太会用上,读者若有兴趣也可以自行探索一下。不管使用什么subprocess方法,使用到的参数几乎都相似,使用的方式也都类似,因此多举一反三即可。

本文与上篇文章相辅相成,希望能在python和linux联动使用的过程中帮助到大家。

参考:https://docs.python.org/zh-cn/3/library/subprocess.html#security-considerations