subprocess模块源码介绍

介绍

subprocess生成新的进程,连接input/output管道,并获取返回码.

常用函数
subprocess.run()执行指定命令完成并返回一个包含执行结果的CompletedProcess类的实例。.call()执行指定的命令,返回命令执行状态check_call()执行指定的命令,如果执行成功则返回状态码,否则抛出异常check_output()执行指定的命令,如果执行状态码为0则返回命令执行结果,否则抛出异常getoutput(cmd)接收字符串格式的命令,执行命令并返回执行结果getstatusoutput(cmd)执行cmd命令,返回一个元组(命令执行状态,命令执行结果输出)

参数说明

args: 执行的shell命令(字符串序列),shell参数值应该为True.shell: shell为True,指定命令通过shell执行.check: 为True,且执行命令的进程以非0状态码退出,则会抛出一个CalledProcessError的异常.stdout,stderr:run() 函数不捕获命令执行结果的正常和错误输出.向获取这些内容传递subprocess.PIPE,然后可以通过返回的CompletedProcess类实例的stdout和stderr属性或捕获相应的内容;call()和check_call()函数返回的是命令执行状态码.check_output() 返回执行命令结果.在结果中捕获错误信息,可以执行stderr=subprocess.STDOUT。input: 该参数值是字节序列.universal_newlines: 影响的是输入与输出的数据格式.

subprocess.CompletedProcess类介绍

表示的是一个已结束进程的状态信息.包含属性如下:

args: 加载该进程的参数.returncode 子进程的退出状态码.stdout: 从子进程捕获的stdout.一个字节序列. 指定universal_newlines=True,则该属性值是一个字符串.stderr: 从子进程捕获的stderr。值是一个字节序列或一个字符串。check_returncode(): 如果returncode是一个非0值,则该方法会抛出一个CalledProcessError异常。.

示例

run()

In [2]: subprocess.run(["ls","-l"])-rw-r--r-- 1 liyuanjie liyuanjie 1350 12月 15 18:33 wireshark.mdOut[2]: CompletedProcess(args=['ls', '-l'], returncode=0)

In [3]: subprocess.run(["ls","-l","/dev/null"],stdout=subprocess.PIPE)
Out[3]: CompletedProcess(args=['ls', '-l', '/dev/null'], returncode=0, stdout=b'
crw-rw-rw- 1 root root 1, 3 12\xe6\x9c\x88 15 07:51 /dev/null\n')

- call()

In [4]: subprocess.call(['ls','-l'])
In [5]: subprocess.call('ls -l',shell=True)

In [6]: subprocess.call(['ls','-l'],stdout=subprocess.DEVNULL)
Out[6]: 0

In [7]: subprocess.call(['ls','-l','/services'])

- check_call()

In [9]: subprocess.check_call(['ls','-l'])
In [10]: subprocess.check_call('ls -l',shell=True)

In [11]: subprocess.check_call('ls -l /services',shell=True)

- check_output()

In [12]: ret = subprocess.check_output(['ls','-l'])
In [13]: print(ret) 返回的是字节序列.

In [14]: ret = subprocess.check_output(['ls','-l'],universal_newlines=True)
In [15]: print(ret) 返回的是字符串.

- getoutput()与getstatusoutput()

In [16]: ret = subprocess.getoutput('ls -l')
In [17]: print(ret)

正确情况下:
In [18]: retcode,output = subprocess.getstatusoutput('ls -l')
In [19]: print(retcode)
0
In [20]: print(output)

错误情况下:
In [21]: retcode,output = subprocess.getstatusoutput('ls -l /test')
In [22]: print(retcode)
2

In [23]: print(output)
ls: cannot access '/test': No such file or directory

subprocess.Popen介绍

该类用于在一个新的进程中执行一个子程序.由于subprocess模块底层的进程创建和管理是由Popen类来处理的. 可以通过subprocess.Popen类提供的灵活的api来完成.

Popen的构造函数

参数说明

args: shell命令.bufsize: 指定缓存策略,0表示不缓冲,1表示行缓冲.负数 表示使用系统默认缓冲策略。stdin,stdout,stderr: 分别表示程序标准输入,输出,错误句柄。preexec_fn: 用于指定一个将在子进程运行之前被调用的可执行对象.close_fds: 值为True时,所有文件描述符都将在子进程执行前关闭.shell: 标识是否使用shell作为要执行的程序.cwd: 该函数会在执行这个子进程之前改变当前工作目录.env: 用于指定子进程的环境变量.universal_newlines为True时,则该文件对象的stdin,stdout和stderr将会作为文本流被打开,否则他们将会被作为二进制流被打开。

Popen类的实例可调用的方法

Popen.poll()检查命令是否已经执行结束.wait(timeout=None)等待子进程结束,返回状态码.communicate()与进程进行交互.send_signal(signal)发送指定的信号给这个子进程terminate()停止该子进程.kill()杀死该子进程.

示例

In [25]: p = subprocess.Popen('df -hT',stdout=subprocess.PIPE,shell=True)In [26]: print(p.stdout.read())In [2]: p1 = subprocess.Popen(['df','-Th'],stdout=subprocess.PIPE)In [3]: p2 = subprocess.Popen(['grep','dev'],stdin=p1.stdout,stdout=subprocess.PIPE)In [4]: out,err = p2.communicate()In [5]: print(out)