python第11次课

关于datetime/time/commands模块的内容可以点击python内置模块查看。

subprocess

subprocess模块用来生成子进程,并可以通过管道连接它们的输入/输出/错误,以及获得它们的返回值。

getoutput(cmd)

该命令类似commands模块中的getoutput(),执行cmd命令返回执行结果。
 

1
2
3
4
5
6
7
>>> PIDS = subprocess.getoutput("netstat -aon | findstr 0:80")
>>> print(PIDS)
  TCP    0.0.0.0:80             0.0.0.0:0              LISTENING       4
>>> PIDS1 = subprocess.getoutput("netstat -aon | grep 0:80")
>>> print(PIDS1)
'grep' 不是内部或外部命令,也不是可运行的程序
或批处理文件。

getstatusoutput(cmd)

该命令类似commands模块中的getstatusoutput(),执行cmd命令返回包含2个元素的元组。
第一个元素为命令执行状态(int),如果执行成功返回0,不成功返回非0。
第二个元素为命令执行结果(str)。

1
2
3
4
5
6
7
8
9
10
11
12
13
>>> import subprocess
>>> PIDS = subprocess.getstatusoutput("netstat -aon | findstr 0:80")
>>> print(PIDS)  #输出结果为元组
(0, '  TCP    0.0.0.0:80             0.0.0.0:0              LISTENING       4\n  TCP    192.168.0.102:64793    111.202.100.60:80      TIME_WAIT       0')
>>> PIDS1 = subprocess.getstatusoutput("netstat -aon | grep 0:80")
>>> print(PIDS1)
(255, "'grep' 不是内部或外部命令,也不是可运行的程序\n或批处理文件。")
>>> status, result = subprocess.getstatusoutput("netstat -aon | grep 0:80")    #python中典型使用方法
>>> print(status)
255
>>> print(result)
'grep' 不是内部或外部命令,也不是可运行的程序
或批处理文件。

call()

参数说明

1
subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None)

执行命令并返回执行状态,其中shell参数为False时,命令需要以列表的方式传入,当shell为True时,可直接传入命令。默认情况下shell=False
shell=False情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
>>> import subprocess
>>> a = subprocess.call("ls")    #单个不带参数的命令可直接执行
anaconda-ks.cfg
>>> print(a)    #命令执行结果
0
>>> b = subprocess.call("ls -l")    #带参数命令直接传入将会报错
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/subprocess.py", line 524, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/usr/lib64/python2.7/subprocess.py", line 711, in __init__
    errread, errwrite)
  File "/usr/lib64/python2.7/subprocess.py", line 1327, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory
>>> b = subprocess.call(["ls", "-l"])    #带参数命令以列表方式传入
total 4
-rw-------. 1 root root 2523 Apr 21  2016 anaconda-ks.cfg
>>> print(b)
0

shell=True情况

1
2
3
4
5
6
>>> import subprocess
>>> a = subprocess.call("ls -l", shell=True)    #带参数命令也可直接传入
total 4
-rw-------. 1 root root 2523 Apr 21  2016 anaconda-ks.cfg
>>> print(a)
0

check_call()

参数说明

1
subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False, timeout=None)

执行命令,若返回状态码为0,则返回0,否则抛出异常CalledProcessError
注意:该方法等价于python3.5中的run(..., check=True)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
>>> import subprocess
>>> a = subprocess.check_call(["ls", "-l"])
total 4
-rw-------. 1 root root 2523 Apr 21  2016 anaconda-ks.cfg
>>> print(a)
0
>>> a = subprocess.check_call("ls -l", shell=True)
total 4
-rw-------. 1 root root 2523 Apr 21  2016 anaconda-ks.cfg
>>> print(a)
0
>>> b = subprocess.check_call("exit 1", shell=True)    #即使正确执行命令,但返回值不为0抛出异常
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/subprocess.py", line 542, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1

check_output()

语法说明

1
args, *, stdin=None, stderr=None, shell=False, universal_newlines=False, timeout=None

执行命令,若返回状态码为0,则返回执行结果,否则抛出异常CalledProcessError
注意:该方法等价于python3.5中的run(..., check=True, stdout=PIPE).stdout

1
2
3
4
5
6
7
8
9
10
11
12
>>> import subprocess
>>> a = subprocess.check_output("ls -l", shell=True)
>>> print(a)    #输出为执行结果
total 4
-rw-------. 1 root root 2523 Apr 21  2016 anaconda-ks.cfg

>>> b = subprocess.check_output("exit 1", shell=True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/subprocess.py", line 575, in check_output
    raise CalledProcessError(retcode, cmd, output=output)
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1

run()

python 3.5添加的函数。
语法说明:

1
subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None)

执行指定命令,等待命令执行完成后返回一个包含执行结果的CompleteProcess类的实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
>>> subprocess.run("dir", shell=True)
 驱动器 C 中的卷没有标签。
 卷的序列号是 A001-9D89

 C:\Users\xiaohuihui 的目录

2018/04/19  20:30    <DIR>          .
2018/04/19  20:30    <DIR>          ..
2017/11/17  10:16    <DIR>          .android
............................................
...........................................
2018/01/23  16:23                 0 2.txt
2018/04/16  06:45    <DIR>          3D Objects
2018/04/13  20:28                 4 bacon.txt
               8 个文件  1,029,964,132 字节
              24 个目录 94,803,804,160 可用字节
CompletedProcess(args='dir', returncode=0)
>>> subprocess.run("exit 1", shell=True, check=True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Users\xiaohuihui\AppData\Local\Programs\Python\Python36\lib\subprocess.py", line 418, in run
    output=stdout, stderr=stderr)
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1.
>>> subprocess.run("netstat -aon|findstr 0:80", shell=True, stdout=subprocess.PIPE)
CompletedProcess(args='netstat -aon|findstr 0:80', returncode=0, stdout=b'  TCP    0.0.0.0:80             0.0.0.0:0              LISTENING       4\r\n')

参数说明

subprocess中的call()check_call()check_output()以及run()参数列表已经列出,下面是参数的说明

  • args
    要执行的shell命令,默认是一个字符串序列,如['df', '-hT']('df', '-hT'),也可以是一个字符串,如'df -hT',但此时需要把shell参数的值设置为True
  • shell
    如果shell为True,那么指定的命令将通过shell执行。如果需要访问某些shell特性,如管道、文件名通配符等,这将非常有用。
  • check
    如果check参数的值是True,且执行命令的进程以非0的状态码退出,则会抛出一个CalledProcessError异常,且该异常对象会包含参数、退出状态码以及stdout和stderr(若被捕获)。
  • stdout/stderr
    程序的标准输出和错误输出。
  • run()函数默认不会捕获命令执行结果的正常输出和错误输出,如果我们想获取这些内容,需要传递subprocess.PIPE然后可以通过返回的CompleteProcess类实例的stddout和stderr属性捕获相应的内容。
  • call()和check_call()函数返回的是命令执行的状态码而不是CompleteProcess类实例,所以它们的stdout和stderr不适合赋值为subprocess.PIPE
  • check_output()函数默认会返回执行结果,所以不用设置stdout的值,如果希望在结果中捕获错误信息,可以设置stderr = subprocess.STDOUT
  • cwd
    用于设置子进程的当前目录。当它不为None时,子程序在执行前,它的当前路径会被替换成cwd的值。这个路径并不会被添加到可执行程序的搜索路径,所以cwd不能是相对路径。
  • input
    该参数是传递给Popen.communicate(),通常该参数的值必须是一个字节序列,如果universal_newline=True,则其值应该是一个字符串。
  • universal_newline
    该参数影响的是输入输出的数据格式,默认为False,此时stdout和stderr的输出是字节序列,设置为True时stdout和stderr的输出是字符串。

CompleteProcess类说明

subprocess.CompleteProcess类在python3.5中才存在,表示一个已经结束进程的状态信息,包含的属性如下

  • args:用于加载进程的参数,可能是一个列表或者一个字符串。
  • returncode:子进程的退出状态码,通常情况下状态码为0表示进程成功运行;负值-N表示子进程被信号N终止。
  • stdout:从子进程捕获的stdout。这通常是一个字节序列,如果run()函数被调用时指定universal_newlines=True,则该属性值是一个字符串。如果run()函数被调用时指定stderr=subprocess.STDOUT,那么stdout和stderr将会被整合到这一个属性中,且stderr将会为None
  • stderr:从子进程捕获的stderr。它的值与stdout一样,是一个字节序列或一个字符串。如果stderr没有被捕获的话,它的值就为None
  • check_returncode(): 如果returncode是一个非0值,则该方法会抛出一个CalledProcessError异常。

Popen

该类用于在一个新的进程中执行一个子程序。上面介绍的函数都是基于subprocess.Popen类实现的,通过使用这些被封装后的高级函数可以很方便的完成一些常见的需求。当无法通过上面的高级函数实现一些不太常用的功能时,可以通过subprocess.Popen来完成。
示例1

1
2
3
4
>>> import subprocess
>>> p = subprocess.Popen("netstat -aon|findstr 0:80", shell=True, stdout=subprocess.PIPE)
>>> print(p.stdout.read())
b'  TCP    0.0.0.0:80             0.0.0.0:0              LISTENING       4\r\n'

示例2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> obj = subprocess.Popen(["python"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
>>> obj.stdin.write('print(1) \n')    #返回写入的字符数
10
>>> obj.stdin.write('print(2) \n')
10
>>> obj.stdin.write('print(3) \n')
10
>>> out,err = obj.communicate()
>>> print(out)
1
2
3

>>> print(err)

总结

  1. Python2.4版本引入了subprocess模块用来替换os.system()、os.popen()、os.spawn*()等函数以及commands模块;也就是说如果你使用的是Python 2.4及以上的版本就应该使用subprocess模块了。
  2. 如果你的应用使用的Python 2.4以上,但是是Python 3.5以下的版本,Python官方给出的建议是使用subprocess.call()函数。Python 2.5中新增了一个subprocess.check_call()函数,Python 2.7中新增了一个subprocess.check_output()函数,这两个函数也可以按照需求进行使用。
  3. 如果你的应用使用的是Python 3.5及以上的版本,Python官方给出的建议是尽量使用subprocess.run()函数。
  4. 当subprocess.call()、subprocess.check_call()、subprocess.check_output()和subprocess.run()这些高级函数无法满足需求时,我们可以使用subprocess.Popen类来实现我们需要的复杂功能。

更多关于subprocess说明可点击查看官方文档。

log

sys

os

猜你喜欢

转载自my.oschina.net/u/3803404/blog/1801248