python模块之subprocess 一、os和commands模块 二、subprocess模块 三、subprocess.Popen
前言:人与人之间的交互的媒介是语言,那人与操作系统之间的交互是通过什么呢?没错是命令,例如Linux系统中的shell。那人与人交互后是想得到对方的回应,比如对方是否真的听懂了,对方听懂后的回应;当然人与操作系统也不例外,我们也可以得到操作系统的回应,如命令是否执行成功的状态码,执行命令成功后的输出结果。当然我们的python也可以完成这些命令的执行,这就要借助今天讲的subprocess库了。在讲subprocess模块之前不得不提一下os和commands模块。早期的Python版本中,我们主要是通过os.system()、os.popen().read()等函数来执行命令行指令的,另外还有一个很少使用的commands模块。但是从Python 2.4开始官方文档中建议使用的是subprocess模块,我们重要要介绍的是subprocess模块。
函数名 | 描述 |
---|---|
os.system(command) | 返回命令执行状态码,而将命令执行结果输出到屏幕 |
os.popen(command).read() | 可以获取命令执行结果,但是无法获取命令执行状态码 |
commands.getstatusoutput(command) | 返回一个元组(命令执行状态码, 命令执行结果) |
注:
1、os.popen(command)函数得到的是一个文件对象,因此除了read()方法外还支持write()等方法,具体要根据command来定;
2、commands模块只存在于Python 2.7中,且不支持windows平台,因此commands模块很少被使用。另外,commands模块实际上也是通过对os.popen()的封装来完成的。
1、os.system()函数实例
qinlang@qinlang-PC:~$ python3 Python 3.7.3 (default, Apr 3 2019, 05:39:12) [GCC 8.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import os >>> os.system('ls -hl') ///不赋值时将结果和返回值直接输出到屏幕 总用量 2.7M drwxr-xr-x 3 root root 4.0K 4月 10 18:17 appstore_deb_check drwxrwxrwx 10 root root 4.0K 4月 9 12:47 dde_robot drwxr-xr-x 3 qinlang qinlang 4.0K 4月 9 12:48 Desktop drwxr-xr-x 3 qinlang qinlang 4.0K 4月 4 22:45 Documents drwxr-xr-x 4 qinlang qinlang 4.0K 4月 6 15:37 Downloads -rw-r--r-- 1 root root 1.5M 4月 16 2016 get-pip.py -rw-r--r-- 1 qinlang qinlang 1.2M 4月 4 20:43 get-pip.zip drwxr-xr-x 3 qinlang qinlang 4.0K 4月 4 14:21 Music drwxr-xr-x 2 qinlang qinlang 4.0K 4月 3 20:46 Pictures drwxr-xr-x 2 qinlang qinlang 4.0K 4月 3 20:52 Videos 0 >>> a = os.system('ls -lh') ///赋值时将结果输出到屏幕,将返回值赋给变量 总用量 2.7M drwxr-xr-x 3 root root 4.0K 4月 10 18:17 appstore_deb_check drwxrwxrwx 10 root root 4.0K 4月 9 12:47 dde_robot drwxr-xr-x 3 qinlang qinlang 4.0K 4月 9 12:48 Desktop drwxr-xr-x 3 qinlang qinlang 4.0K 4月 4 22:45 Documents drwxr-xr-x 4 qinlang qinlang 4.0K 4月 6 15:37 Downloads -rw-r--r-- 1 root root 1.5M 4月 16 2016 get-pip.py -rw-r--r-- 1 qinlang qinlang 1.2M 4月 4 20:43 get-pip.zip drwxr-xr-x 3 qinlang qinlang 4.0K 4月 4 14:21 Music drwxr-xr-x 2 qinlang qinlang 4.0K 4月 3 20:46 Pictures drwxr-xr-x 2 qinlang qinlang 4.0K 4月 3 20:52 Videos >>> a ///调用变量时直接出现变量码,0代表命令执行成功 0 >>>
2、os.popen()函数实例
qinlang@qinlang-PC:~$ python3 Python 3.7.3 (default, Apr 3 2019, 05:39:12) [GCC 8.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import os >>> os.popen('ls -hl').read() ///直接输出结果,无返回码,可将结果赋值给变量使用 '总用量 2.7M drwxr-xr-x 3 root root 4.0K 4月 10 18:17 appstore_deb_check drwxrwxrwx 10 root root 4.0K 4月 9 12:47 dde_robot drwxr-xr-x 3 qinlang qinlang 4.0K 4月 9 12:48 Desktop drwxr-xr-x 3 qinlang qinlang 4.0K 4月 4 22:45 Documents drwxr-xr-x 4 qinlang qinlang 4.0K 4月 6 15:37 Downloads -rw-r--r-- 1 root root 1.5M 4月 16 2016 get-pip.py -rw-r--r-- 1 qinlang qinlang 1.2M 4月 4 20:43 get-pip.zip drwxr-xr-x 3 qinlang qinlang 4.0K 4月 4 14:21 Music drwxr-xr-x 2 qinlang qinlang 4.0K 4月 3 20:46 Pictures drwxr-xr-x 2 qinlang qinlang 4.0K 4月 3 20:52 Videos ' >>>
commands具体实例就不展示了,现在电脑使用的是python3.7.3的版本,commands模块已经被subprocess完全代替了。
二、subprocess模块
1、简介
subprocess模块可以生成新的进程,连接到它们的input/output/error管道,同时获取它们的返回码。(此模块是python2.4之后才有的)这个模块的目的在于替换几个旧的模块和方法,如:os.system、os.spawn*
以下是subprocess常用函数及描述:
函数 | 描述 |
---|---|
subprocess.run() | Python 3.5中新增的函数。执行指定的命令,等待命令执行完成后返回一个包含执行结果的CompletedProcess类的实例。 |
subprocess.call() | 执行指定的命令,返回命令执行状态,其功能类似于os.system(cmd)。 |
subprocess.check_call() | Python 2.5中新增的函数。 执行指定的命令,如果执行成功则返回状态码,否则抛出异常。其功能等价于subprocess.run(..., check=True)。 |
subprocess.check_output() | Python 2.7中新增的的函数。执行指定的命令,如果执行状态码为0则返回命令执行结果,否则抛出异常。 |
subprocess.getoutput(cmd) | 接收字符串格式的命令,执行命令并返回执行结果,其功能类似于os.popen(cmd).read()和commands.getoutput(cmd)。 |
subprocess.getstatusoutput(cmd) | 执行cmd命令,返回一个元组(命令执行状态, 命令执行结果输出),其功能类似于commands.getstatusoutput()。 |
注:
- subprocess.run()、subprocess.call()、subprocess.check_call()和subprocess.check_output()都是通过对subprocess.Popen的封装来实现的高级函数,因此如果我们需要更复杂功能时,可以通过subprocess.Popen来完成。
- subprocess.getoutput()和subprocess.getstatusoutput()函数是来自Python 2.x的commands模块的两个遗留函数。它们隐式的调用系统shell,并且不保证其他函数所具有的安全性和异常处理的一致性。另外,它们从Python 3.3.4开始才支持Windows平台。
2、subprocess.run()函数实例
>>> import subprocess >>> subprocess.run(['ls', '-lh']) ///用法1、args是字符串序列(列表或者元组),命令执行后的结果输出到屏幕上,函数返回值CompletedProcess中包含有args和returncode; 总用量 2.7M drwxr-xr-x 3 root root 4.0K 4月 10 18:17 appstore_deb_check drwxrwxrwx 10 root root 4.0K 4月 9 12:47 dde_robot drwxr-xr-x 3 qinlang qinlang 4.0K 4月 9 12:48 Desktop drwxr-xr-x 3 qinlang qinlang 4.0K 4月 4 22:45 Documents drwxr-xr-x 4 qinlang qinlang 4.0K 4月 6 15:37 Downloads -rw-r--r-- 1 root root 1.5M 4月 16 2016 get-pip.py -rw-r--r-- 1 qinlang qinlang 1.2M 4月 4 20:43 get-pip.zip drwxr-xr-x 3 qinlang qinlang 4.0K 4月 4 14:21 Music drwxr-xr-x 2 qinlang qinlang 4.0K 4月 3 20:46 Pictures drwxr-xr-x 2 qinlang qinlang 4.0K 4月 3 20:52 Videos CompletedProcess(args=['ls', '-lh'], returncode=0) >>> subprocess.run('ls -lh', shell = True) ///用法2:args是字符串时,shell必须为True,命令执行后的结果输出到屏幕上,函数返回值CompletedProcess中包含有args和returncode; 总用量 2.7M drwxr-xr-x 3 root root 4.0K 4月 10 18:17 appstore_deb_check drwxrwxrwx 10 root root 4.0K 4月 9 12:47 dde_robot drwxr-xr-x 3 qinlang qinlang 4.0K 4月 9 12:48 Desktop drwxr-xr-x 3 qinlang qinlang 4.0K 4月 4 22:45 Documents drwxr-xr-x 4 qinlang qinlang 4.0K 4月 6 15:37 Downloads -rw-r--r-- 1 root root 1.5M 4月 16 2016 get-pip.py -rw-r--r-- 1 qinlang qinlang 1.2M 4月 4 20:43 get-pip.zip drwxr-xr-x 3 qinlang qinlang 4.0K 4月 4 14:21 Music drwxr-xr-x 2 qinlang qinlang 4.0K 4月 3 20:46 Pictures drwxr-xr-x 2 qinlang qinlang 4.0K 4月 3 20:52 Videos CompletedProcess(args='ls -lh', returncode=0) >>> subprocess.run('lsk -lh', shell = True, check = True) ///用法3:args是字符串,指定shell为True,check为True,执行命令的进程以非0状态码退出,则会抛出一个CalledProcessError的异常 /bin/sh: 1: lsk: not found Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python3.7/subprocess.py", line 487, in run output=stdout, stderr=stderr) subprocess.CalledProcessError: Command 'lsk -lh' returned non-zero exit status 127. >>> subprocess.run(['ls', '-lh'],stdout = subprocess.PIPE) ///用法4:args是字符串序列,指定stdout标准输出,命令执行后的结果输出到stdout中,函数返回值CompletedProcess中包含有args、returncode和stdout; CompletedProcess(args=['ls', '-lh'], returncode=0, stdout=b'xe6x80xbbxe7x94xa8xe9x87x8f 2.7M drwxr-xr-x 3 root root 4.0K 4xe6x9cx88 10 18:17 appstore_deb_check drwxrwxrwx 10 root root 4.0K 4xe6x9cx88 9 12:47 dde_robot drwxr-xr-x 3 qinlang qinlang 4.0K 4xe6x9cx88 9 12:48 Desktop drwxr-xr-x 3 qinlang qinlang 4.0K 4xe6x9cx88 4 22:45 Documents drwxr-xr-x 4 qinlang qinlang 4.0K 4xe6x9cx88 6 15:37 Downloads -rw-r--r-- 1 root root 1.5M 4xe6x9cx88 16 2016 get-pip.py -rw-r--r-- 1 qinlang qinlang 1.2M 4xe6x9cx88 4 20:43 get-pip.zip drwxr-xr-x 3 qinlang qinlang 4.0K 4xe6x9cx88 4 14:21 Music drwxr-xr-x 2 qinlang qinlang 4.0K 4xe6x9cx88 3 20:46 Pictures drwxr-xr-x 2 qinlang qinlang 4.0K 4xe6x9cx88 3 20:52 Videos ') >>>
3、subprocess.call()函数实例
qinlang@qinlang-PC:~$ python3 Python 3.7.3 (default, Apr 3 2019, 05:39:12) [GCC 8.3.0] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import subprocess >>> subprocess.call(['ls', '-lh']) ///用法1:args为字符串序列,输出结果到屏幕,返回状态为0成功 总用量 2.7M drwxr-xr-x 3 root root 4.0K 4月 10 18:17 appstore_deb_check drwxrwxrwx 10 root root 4.0K 4月 9 12:47 dde_robot drwxr-xr-x 3 qinlang qinlang 4.0K 4月 9 12:48 Desktop drwxr-xr-x 3 qinlang qinlang 4.0K 4月 4 22:45 Documents drwxr-xr-x 4 qinlang qinlang 4.0K 4月 6 15:37 Downloads -rw-r--r-- 1 root root 1.5M 4月 16 2016 get-pip.py -rw-r--r-- 1 qinlang qinlang 1.2M 4月 4 20:43 get-pip.zip drwxr-xr-x 3 qinlang qinlang 4.0K 4月 4 14:21 Music drwxr-xr-x 2 qinlang qinlang 4.0K 4月 3 20:46 Pictures drwxr-xr-x 2 qinlang qinlang 4.0K 4月 3 20:52 Videos 0 >>> subprocess.call('ls -hl', shell = True) ///用法1:args为字符串,此时shell为True,输出结果到屏幕,返回状态为0成功 总用量 2.7M drwxr-xr-x 3 root root 4.0K 4月 10 18:17 appstore_deb_check drwxrwxrwx 10 root root 4.0K 4月 9 12:47 dde_robot drwxr-xr-x 3 qinlang qinlang 4.0K 4月 9 12:48 Desktop drwxr-xr-x 3 qinlang qinlang 4.0K 4月 4 22:45 Documents drwxr-xr-x 4 qinlang qinlang 4.0K 4月 6 15:37 Downloads -rw-r--r-- 1 root root 1.5M 4月 16 2016 get-pip.py -rw-r--r-- 1 qinlang qinlang 1.2M 4月 4 20:43 get-pip.zip drwxr-xr-x 3 qinlang qinlang 4.0K 4月 4 14:21 Music drwxr-xr-x 2 qinlang qinlang 4.0K 4月 3 20:46 Pictures drwxr-xr-x 2 qinlang qinlang 4.0K 4月 3 20:52 Videos 0 >>> subprocess.call('ls -hl', shell = True, stdout=subprocess.PIPE) ///输出结果到stdout 0
4、subprocess.check_call()函数实例
>>> subprocess.check_call(['ls', '-ls']) 总用量 2748 4 drwxr-xr-x 3 root root 4096 4月 10 18:17 appstore_deb_check 4 drwxrwxrwx 10 root root 4096 4月 9 12:47 dde_robot 4 drwxr-xr-x 3 qinlang qinlang 4096 4月 9 12:48 Desktop 4 drwxr-xr-x 3 qinlang qinlang 4096 4月 4 22:45 Documents 4 drwxr-xr-x 4 qinlang qinlang 4096 4月 6 15:37 Downloads 1508 -rw-r--r-- 1 root root 1541964 4月 16 2016 get-pip.py 1208 -rw-r--r-- 1 qinlang qinlang 1233079 4月 4 20:43 get-pip.zip 4 drwxr-xr-x 3 qinlang qinlang 4096 4月 4 14:21 Music 4 drwxr-xr-x 2 qinlang qinlang 4096 4月 3 20:46 Pictures 4 drwxr-xr-x 2 qinlang qinlang 4096 4月 3 20:52 Videos 0 >>> a = subprocess.check_call('ls -lh', shell = True) 总用量 2.7M drwxr-xr-x 3 root root 4.0K 4月 10 18:17 appstore_deb_check drwxrwxrwx 10 root root 4.0K 4月 9 12:47 dde_robot drwxr-xr-x 3 qinlang qinlang 4.0K 4月 9 12:48 Desktop drwxr-xr-x 3 qinlang qinlang 4.0K 4月 4 22:45 Documents drwxr-xr-x 4 qinlang qinlang 4.0K 4月 6 15:37 Downloads -rw-r--r-- 1 root root 1.5M 4月 16 2016 get-pip.py -rw-r--r-- 1 qinlang qinlang 1.2M 4月 4 20:43 get-pip.zip drwxr-xr-x 3 qinlang qinlang 4.0K 4月 4 14:21 Music drwxr-xr-x 2 qinlang qinlang 4.0K 4月 3 20:46 Pictures drwxr-xr-x 2 qinlang qinlang 4.0K 4月 3 20:52 Videos >>> a 0 >>> a = subprocess.check_call('lss -lh', shell = True) ///执行失败抛出CalledProcessError异常 /bin/sh: 1: lss: not found Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python3.7/subprocess.py", line 347, in check_call raise CalledProcessError(retcode, cmd) subprocess.CalledProcessError: Command 'lss -lh' returned non-zero exit status 127.
5、subprocess.check_output()函数实例
>>> subprocess.check_output('ls -hl', shell = True) ///执行成功输出结果 b'xe6x80xbbxe7x94xa8xe9x87x8f 2.7M drwxr-xr-x 3 root root 4.0K 4xe6x9cx88 10 18:17 appstore_deb_check drwxrwxrwx 10 root root 4.0K 4xe6x9cx88 9 12:47 dde_robot drwxr-xr-x 3 qinlang qinlang 4.0K 4xe6x9cx88 9 12:48 Desktop drwxr-xr-x 3 qinlang qinlang 4.0K 4xe6x9cx88 4 22:45 Documents drwxr-xr-x 4 qinlang qinlang 4.0K 4xe6x9cx88 6 15:37 Downloads -rw-r--r-- 1 root root 1.5M 4xe6x9cx88 16 2016 get-pip.py -rw-r--r-- 1 qinlang qinlang 1.2M 4xe6x9cx88 4 20:43 get-pip.zip drwxr-xr-x 3 qinlang qinlang 4.0K 4xe6x9cx88 4 14:21 Music drwxr-xr-x 2 qinlang qinlang 4.0K 4xe6x9cx88 3 20:46 Pictures drwxr-xr-x 2 qinlang qinlang 4.0K 4xe6x9cx88 3 20:52 Videos ' >>> subprocess.check_output('lsl -hl ', shell = True) ///执行失败抛出CalledProcessError异常 /bin/sh: 1: lsl: not found Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/lib/python3.7/subprocess.py", line 395, in check_output **kwargs).stdout File "/usr/lib/python3.7/subprocess.py", line 487, in run output=stdout, stderr=stderr) subprocess.CalledProcessError: Command 'lsl -hl ' returned non-zero exit status 127.
6、subprocess.getoutput()与subprocess.getstatusoutput()函数实例
>>> subprocess.getoutput('ls -hl') //args为命令的字符串类型,返回字符串类型的执行成功后的结果,执行失败不会报错 '总用量 2.7M drwxr-xr-x 3 root root 4.0K 4月 10 18:17 appstore_deb_check drwxrwxrwx 10 root root 4.0K 4月 9 12:47 dde_robot drwxr-xr-x 3 qinlang qinlang 4.0K 4月 9 12:48 Desktop drwxr-xr-x 3 qinlang qinlang 4.0K 4月 4 22:45 Documents drwxr-xr-x 4 qinlang qinlang 4.0K 4月 6 15:37 Downloads -rw-r--r-- 1 root root 1.5M 4月 16 2016 get-pip.py -rw-r--r-- 1 qinlang qinlang 1.2M 4月 4 20:43 get-pip.zip drwxr-xr-x 3 qinlang qinlang 4.0K 4月 4 14:21 Music drwxr-xr-x 2 qinlang qinlang 4.0K 4月 3 20:46 Pictures drwxr-xr-x 2 qinlang qinlang 4.0K 4月 3 20:52 Videos' >>> subprocess.getstatusoutput('ls -hl') ///args为命令的字符串类型,返回元组类型的执行成功状态码0和结果 (0, '总用量 2.7M drwxr-xr-x 3 root root 4.0K 4月 10 18:17 appstore_deb_check drwxrwxrwx 10 root root 4.0K 4月 9 12:47 dde_robot drwxr-xr-x 3 qinlang qinlang 4.0K 4月 9 12:48 Desktop drwxr-xr-x 3 qinlang qinlang 4.0K 4月 4 22:45 Documents drwxr-xr-x 4 qinlang qinlang 4.0K 4月 6 15:37 Downloads -rw-r--r-- 1 root root 1.5M 4月 16 2016 get-pip.py -rw-r--r-- 1 qinlang qinlang 1.2M 4月 4 20:43 get-pip.zip drwxr-xr-x 3 qinlang qinlang 4.0K 4月 4 14:21 Music drwxr-xr-x 2 qinlang qinlang 4.0K 4月 3 20:46 Pictures drwxr-xr-x 2 qinlang qinlang 4.0K 4月 3 20:52 Videos') >>> subprocess.getstatusoutput('ls -hl /lksks') ///执行失败返回元组类型的状态码2和结果 (2, "ls: 无法访问'/lksks': 没有那个文件或目录")
三、subprocess.Popen
1、简介
实际上以上所有的方法都是通过对subprocess.Popen类型封装来实现的,该类用于在一个新的进程中执行一个子程序。当我们无法通过以上高级函数来完成所需工作的时,我们可以考虑使用封装subprocess.Popen来完成。
2、subprocess.Popen的构造函数
class subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=False, startup_info=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=())
参数说明:
- 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()函数,用于设置子进程的一些属性,如主窗口的外观,进程优先级等。
3、 subprocess.Popen类的实例可调用的方法
方法 | 描述 |
---|---|
Popen.poll() | 用于检查子进程(命令)是否已经执行结束,没结束返回None,结束后返回状态码。 |
Popen.wait(timeout=None) | 等待子进程结束,并返回状态码;如果在timeout指定的秒数之后进程还没有结束,将会抛出一个TimeoutExpired异常。 |
Popen.communicate(input=None, timeout=None) |
该方法可用来与进程进行交互,比如发送数据到stdin,从stdout和stderr读取数据,直到到达文件末尾。
input:表示将发送到子进程的字符串数据,默认为None;
timeout:超时判断,若超过timeout秒后仍未结束则抛出TimeoutExpired异常; communicate返回值:一个元组(stdout_data, stderr_data) |
Popen.send_signal(signal) | 发送指定的信号给这个子进程。 |
Popen.terminate() | 停止该子进程。 |
Popen.kill() |
杀死该子进程。 |