python模块之subprocess 一、os和commands模块 二、subprocess模块 三、subprocess.Popen  

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()。

 注:

  1. subprocess.run()、subprocess.call()、subprocess.check_call()和subprocess.check_output()都是通过对subprocess.Popen的封装来实现的高级函数,因此如果我们需要更复杂功能时,可以通过subprocess.Popen来完成。
  2. 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()

杀死该子进程。