python3之subprocess常见方法使用

时间:2021-02-19 23:58:01

一、常见subprocess方法

1、subprocess.getstatusoutput(cmd)

官方解释:

Return (exitcode, output) of executing cmd in a shell.

Execute the string 'cmd' in a shell with 'check_output' and
return a 2-tuple (status, output). The locale encoding is used
to decode the output and process newlines.

cmd可以直接执行shell命令,而不需要cmd命令以列表输入----subprocess.getstatusoutput("cat /proc/meminfo")

返回值包含cmd的执行状态和执行结果,可以直接赋值给某个变量

实例:

>>> ret = subprocess.getoutput('ls -l')
>>> print(ret)
总用量 160
drwxr-xr-x  2 wader wader   4096 12月  7  2015 公共的
drwxr-xr-x  2 wader wader   4096 12月  7  2015 模板
drwxr-xr-x  2 wader wader   4096 12月  7  2015 视频
drwxr-xr-x  2 wader wader   4096 12月  7  2015 图片
drwxr-xr-x  2 wader wader   4096 12月  7  2015 文档
drwxr-xr-x  2 wader wader   4096  4月 13  2016 下载
drwxr-xr-x  2 wader wader   4096 12月  7  2015 音乐
drwxr-xr-x  7 wader wader   4096  5月 26  2016 桌面
>>> retcode, output = subprocess.getstatusoutput('ls -l')
>>> print(retcode)
0
>>> print(output)
总用量 160
drwxr-xr-x  2 wader wader   4096 12月  7  2015 公共的
drwxr-xr-x  2 wader wader   4096 12月  7  2015 模板
drwxr-xr-x  2 wader wader   4096 12月  7  2015 视频
drwxr-xr-x  2 wader wader   4096 12月  7  2015 图片
drwxr-xr-x  2 wader wader   4096 12月  7  2015 文档
drwxr-xr-x  2 wader wader   4096  4月 13  2016 下载
drwxr-xr-x  2 wader wader   4096 12月  7  2015 音乐
drwxr-xr-x  7 wader wader   4096  5月 26  2016 桌面
>>> retcode, output = subprocess.getstatusoutput('ls -l /test')
>>> print(retcode)
2
>>> print(output)
ls: 无法访问/test: 没有那个文件或目录

 

 

2、subprocess.getoutput(cmd)

官方解释:

Return output (stdout or stderr) of executing cmd in a shell.

Like getstatusoutput(), except the exit status is ignored and the return
value is a string containing the command's output

cmd可以直接执行shell命令,而不需要cmd命令以列表输入---subprocess.getoutput("cat /proc/meminfo")
返回值包含cmd的执行结果,可以直接赋值给某个变量
功能和getstatusoutput类似

3、subprocess.run(*popenargs, input=None, timeout=None, check=False, **kwargs))

Run command with arguments and return a CompletedProcess instance.   执行传入命令参数后,返回CompletedProcess实例
The returned instance will have attributes args, returncode, stdout and
stderr. By default, stdout and stderr are not captured, and those attributes
will be None. Pass stdout=PIPE and/or stderr=PIPE in order to capture them.


check等于True的时候,当执行状态不是0时,会抛出CalledProcessError异常提示

传入命令参数时,需要以多个命令拆分按照列表形式传入:subprocess.run(['df', '-h'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)

如果传入参数同时传入shell=True,则传入一个字符串args,shell命令而不是待执行的shell命令序列

实例:
>>> subprocess.run(["ls", "-l"])  # doesn't capture output
CompletedProcess(args=['ls', '-l'], returncode=0)

>>> subprocess.run("exit 1", shell=True, check=True)
Traceback (most recent call last):
  ...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1

>>> subprocess.run(["ls", "-l", "/dev/null"], stdout=subprocess.PIPE)
CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0,
stdout=b'crw-rw-rw- 1 root root 1, 3 Jan 23 16:23 /dev/null\n')
 

 

 

4、subprocess.call()

官方解释:

Run command with arguments. Wait for command to complete or
timeout, then return the returncode attribute

 传入shell命令参数格式subprocess.check_call(["ls""-l"])

如果传入参数同时传入shell=True,则可以传入一个字符串shell命令而不是待执行的shell命令列表--subprocess.check_call("exit 1", shell=True)
返回参数仅返回执行状态码,可通过把结果复制给某个变量查看,如果直接在linux下python编译器执行该命令会直接显示命令执行的结果

实例:
>>> subprocess.call(['ls',  '-l'])
总用量 160
drwxr-xr-x  2 wader wader   4096 12月  7  2015 公共的
drwxr-xr-x  2 wader wader   4096 12月  7  2015 模板
drwxr-xr-x  2 wader wader   4096 12月  7  2015 视频
drwxr-xr-x  2 wader wader   4096 12月  7  2015 图片
drwxr-xr-x  2 wader wader   4096 12月  7  2015 文档
drwxr-xr-x  2 wader wader   4096  4月 13  2016 下载
drwxr-xr-x  2 wader wader   4096 12月  7  2015 音乐
drwxr-xr-x  7 wader wader   4096  5月 26  2016 桌面
0
>>> subprocess.call('ls -l', shell=True)
总用量 160
drwxr-xr-x  2 wader wader   4096 12月  7  2015 公共的
drwxr-xr-x  2 wader wader   4096 12月  7  2015 模板
drwxr-xr-x  2 wader wader   4096 12月  7  2015 视频
drwxr-xr-x  2 wader wader   4096 12月  7  2015 图片
drwxr-xr-x  2 wader wader   4096 12月  7  2015 文档
drwxr-xr-x  2 wader wader   4096  4月 13  2016 下载
drwxr-xr-x  2 wader wader   4096 12月  7  2015 音乐
drwxr-xr-x  7 wader wader   4096  5月 26  2016 桌面
0
>>> subprocess.call(['ls',  '-l'], stdout=subprocess.DEVNULL)
0
>>> subprocess.call(['ls',  '-l', '/test'])
ls: 无法访问/test: 没有那个文件或目录
2

 

5、subprocess.check_call()

官方解释:

Run command with arguments.  Wait for command to complete.  If
the exit code was zero then return, otherwise raise
CalledProcessError. The CalledProcessError object will have the
return code in the returncode attribute.

check_call基本和call功能一样,只是增加了返回状态码校验,如果执行状态码是0,则返回0,否则抛出异常

实例:

>>> subprocess.check_call(['ls',  '-l'])
总用量 160
drwxr-xr-x  2 wader wader   4096 12月  7  2015 公共的
drwxr-xr-x  2 wader wader   4096 12月  7  2015 模板
drwxr-xr-x  2 wader wader   4096 12月  7  2015 视频
drwxr-xr-x  2 wader wader   4096 12月  7  2015 图片
drwxr-xr-x  2 wader wader   4096 12月  7  2015 文档
drwxr-xr-x  2 wader wader   4096  4月 13  2016 下载
drwxr-xr-x  2 wader wader   4096 12月  7  2015 音乐
drwxr-xr-x  7 wader wader   4096  5月 26  2016 桌面
0
>>> subprocess.check_call('ls -l', shell=True)
总用量 160
drwxr-xr-x  2 wader wader   4096 12月  7  2015 公共的
drwxr-xr-x  2 wader wader   4096 12月  7  2015 模板
drwxr-xr-x  2 wader wader   4096 12月  7  2015 视频
drwxr-xr-x  2 wader wader   4096 12月  7  2015 图片
drwxr-xr-x  2 wader wader   4096 12月  7  2015 文档
drwxr-xr-x  2 wader wader   4096  4月 13  2016 下载
drwxr-xr-x  2 wader wader   4096 12月  7  2015 音乐
drwxr-xr-x  7 wader wader   4096  5月 26  2016 桌面
0
>>> subprocess.check_call('ls -l /test', shell=True)
ls: 无法访问/test: 没有那个文件或目录
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.4/subprocess.py", line 557, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command 'ls -l /test' returned non-zero exit status 2

 

6、subprocess.check_output()

官方解释:

Run command with arguments and return its output.

If the exit code was non-zero it raises a CalledProcessError. The
CalledProcessError object will have the return code in the returncode
attribute and output in the output attribute.
执行命令,如果状态码是0,则返回执行结果,否则抛出异常--
subprocess.check_output(["ls""-l"])
如果传入参数同时传入shell=True,则可以传入一个字符串shell命令而不是待执行的shell命令列表--
subprocess.check_call("exit 1", shell=True)
返回值包含cmd的执行结果,可以直接赋值给某个变量

实例:
>>> ret = subprocess.check_output(['ls',  '-l'])
>>> print(ret)
b' \xe5\x85\xac\xe5\x85\xb1\xe7\x9a\x84\ndrwxr-xr-x  2 wader wader   4096 12\xe6\x9c\x88  7  2015 \xe6\xa8\xa1\xe6\x9d\xbf\ndrwxr-xr-x  2 wader wader   4096 12\xe6\x9c\x88  7  2015 \xe8\xa7\x86\xe9\xa2\x91\ndrwxr-xr-x  2 wader wader   4096 12\xe6\x9c\x88  7  2015 \xe5\x9b\xbe\xe7\x89\x87\ndrwxr-xr-x  2 wader wader   4096 12\xe6\x9c\x88  7  2015 \xe6\x96\x87\xe6\xa1\xa3\ndrwxr-xr-x  2 wader wader   4096  4\xe6\x9c\x88 13  2016 \xe4\xb8\x8b\xe8\xbd\xbd\ndrwxr-xr-x  2 wader wader   4096 12\xe6\x9c\x88  7  2015 \xe9\x9f\xb3\xe4\xb9\x90\ndrwxr-xr-x  7 wader wader   4096  5\xe6\x9c\x88 26  2016 \xe6\xa1\x8c\xe9\x9d\xa2\n'
>>> ret = subprocess.check_output(['ls',  '-l'], universal_newlines=True)
>>> print(ret)
总用量 160
drwxr-xr-x  2 wader wader   4096 12月  7  2015 公共的
drwxr-xr-x  2 wader wader   4096 12月  7  2015 模板
drwxr-xr-x  2 wader wader   4096 12月  7  2015 视频
drwxr-xr-x  2 wader wader   4096 12月  7  2015 图片
drwxr-xr-x  2 wader wader   4096 12月  7  2015 文档
drwxr-xr-x  2 wader wader   4096  4月 13  2016 下载
drwxr-xr-x  2 wader wader   4096 12月  7  2015 音乐
drwxr-xr-x  7 wader wader   4096  5月 26  2016 桌面

 

二、subprocess.Popen()类--用于执行复杂的系统命令

该类用于在一个新的进程中执行一个子程序。前面我们提到过,上面介绍的这些函数都是基于subprocess.Popen类实现的,通过使用这些被封装后的高级函数可以很方面的完成一些常见的需求。由于subprocess模块底层的进程创建和管理是由Popen类来处理的,因此,当我们无法通过上面哪些高级函数来实现一些不太常见的功能时就可以通过subprocess.Popen类提供的灵活的api来完成。

1、subprocess.Popen的构造函数

def __init__(self, args, bufsize=-1, executable=None,
                 stdin=None, stdout=None, stderr=None,
                 preexec_fn=None, close_fds=_PLATFORM_DEFAULT_CLOSE_FDS,
                 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)

构造函数详细参数说明和其他实现过程可以参考对应subprocess库文件

参数说明:

  • args: 要执行的shell命令,可以是字符串,也可以是命令各个参数组成的序列。当该参数的值是一个字符串时,该命令的解释过程是与平台相关的,因此通常建议将args参数作为一个序列传递。
  • bufsize: 指定缓存策略,0表示不缓冲,1表示行缓冲,其他大于1的数字表示缓冲区大小,负数 表示使用系统默认缓冲策略。
  • stdin, stdout, stderr: 分别表示程序标准输入、输出、错误句柄。
  • preexec_fn: 用于指定一个将在子进程运行之前被调用的可执行对象,只在Unix平台下有效。
  • close_fds: 如果该参数的值为True,则除了0,1和2之外的所有文件描述符都将会在子进程执行之前被关闭。
  • shell: 该参数用于标识是否使用shell作为要执行的程序,如果shell值为True,则建议将args参数作为一个字符串传递而不要作为一个序列传递。
  • cwd: 如果该参数值不是None,则该函数将会在执行这个子进程之前改变当前工作目录。
  • env: 用于指定子进程的环境变量,如果env=None,那么子进程的环境变量将从父进程中继承。如果env!=None,它的值必须是一个映射对象。
  • universal_newlines: 如果该参数值为True,则该文件对象的stdin,stdout和stderr将会作为文本流被打开,否则他们将会被作为二进制流被打开。
  • startupinfo和creationflags: 这两个参数只在Windows下有效,它们将被传递给底层的CreateProcess()函数,用于设置子进程的一些属性,如主窗口的外观,进程优先级等。

2. subprocess.Popen类的实例可调用的方法

方法 描述
Popen.poll() 用于检查子进程(命令)是否已经执行结束,没结束返回None,结束后返回状态码。
Popen.wait(timeout=None) 等待子进程结束,并返回状态码;如果在timeout指定的秒数之后进程还没有结束,将会抛出一个TimeoutExpired异常。
Popen.communicate(input=None, timeout=None) 该方法可用来与进程进行交互,比如发送数据到stdin,从stdout和stderr读取数据,直到到达文件末尾。
Popen.send_signal(signal) 发送指定的信号给这个子进程。
Popen.terminate() 停止该子进程。
Popen.kill() 杀死该子进程。

关于communicate()方法的说明:

  • 该方法中的可选参数 input 应该是将被发送给子进程的数据,或者如没有数据发送给子进程,该参数应该是None。input参数的数据类型必须是字节串,如果universal_newlines参数值为True,则input参数的数据类型必须是字符串。
  • 该方法返回一个元组(stdout_data, stderr_data),这些数据将会是字节穿或字符串(如果universal_newlines的值为True)。
  • 如果在timeout指定的秒数后该进程还没有结束,将会抛出一个TimeoutExpired异常。捕获这个异常,然后重新尝试通信不会丢失任何输出的数据。但是超时之后子进程并没有被杀死,为了合理的清除相应的内容,一个好的应用应该手动杀死这个子进程来结束通信。
  • 需要注意的是,这里读取的数据是缓冲在内存中的,所以,如果数据大小非常大或者是无限的,就不应该使用这个方法

3. subprocess.Popen使用实例

实例1、

>>> import subprocess
>>>
>>> p = subprocess.Popen('df -Th', stdout=subprocess.PIPE, shell=True)
>>> print(p.stdout.read())
Filesystem     Type      Size  Used Avail Use% Mounted on
/dev/vda1      ext4       40G   12G   26G  31% /
devtmpfs       devtmpfs  3.9G     0  3.9G   0% /dev
tmpfs          tmpfs     3.9G     0  3.9G   0% /dev/shm
tmpfs          tmpfs     3.9G  386M  3.5G  10% /run
tmpfs          tmpfs     3.9G     0  3.9G   0% /sys/fs/cgroup
tmpfs          tmpfs     783M     0  783M   0% /run/user/0
tmpfs          tmpfs     783M     0  783M   0% /run/user/1000

实例2

>>> obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> obj.stdin.write('print(1) \n')
>>> obj.stdin.write('print(2) \n')
>>> obj.stdin.write('print(3) \n')
>>> out,err = obj.communicate()
>>> print(out)
1
2
3

>>> print(err)

实例3

>>> obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
>>> out,err = obj.communicate(input='print(1) \n')
>>> print(out)
1

>>> print(err)

实例4

实现类似df -Th | grep data命令的功能,实际上就是实现shell中管道的共功能

>>> 
>>> p1 = subprocess.Popen(['df', '-Th'], stdout=subprocess.PIPE)
>>> p2 = subprocess.Popen(['grep', 'data'], stdin=p1.stdout, stdout=subprocess.PIPE)
>>> out,err = p2.communicate()
>>> print(out)
/dev/vdb1      ext4      493G  4.8G  463G   2% /data
/dev/vdd1      ext4     1008G  420G  537G  44% /data1
/dev/vde1      ext4      985G  503G  432G  54% /data2

>>> print(err)
None

三、总结

那么我们到底该用哪个模块、哪个函数来执行命令与系统及系统进行交互呢?下面我们来做个总结:

1、如果你的应用使用的Python 2.4以上,但是是Python 3.5以下的版本,Python官方给出的建议是使用subprocess.call()函数。Python 2.5中新增了一个subprocess.check_call()函数,Python 2.7中新增了一个subprocess.check_output()函数,这两个函数也可以按照需求进行使用

2、如果你的应用使用的是Python 3.5及以上的版本(目前应该还很少),Python官方给出的建议是尽量使用subprocess.run()函数

3、当subprocess.call()、subprocess.check_call()、subprocess.check_output()和subprocess.run()这些高级函数无法满足需求时,我们可以使用subprocess.Popen类来实现我们需要的复杂功能

不过经过个人试验认为getoutput、getstatusoutput方法使用比较便捷,subprocess适合个性化的执行

参考链接:https://www.cnblogs.com/yyds/p/7288916.html