subprocess主要用来和操作系统进行交互,通过subprocess,python可以调用系统命令
我们已经了解到,存在os模块,可以执行系统命令:
>>> import os
>>> os.system('cd')
C:\Users\Administrator
0os.system输出命令结果到屏幕,并且返回命令执行状态
但是,我们尝试将命令结果进行保存时,发现只是保存了命令的执行状态
>>> res =  os.system('cd')
C:\Users\Administrator
>>> print(res)
00为命令执行成功,1为失败
 
为了将命令结果保存在内存中,此时需要使用os.popen
>>> res = os.popen('cd')
>>> print(res)
<os._wrap_close object at 0x00000203DA6339B0>此时,res已经才成为一个内存对象,需要通过read()来读取数据
>>> res.read()
'C:\\Users\\Administrator\n'在python2.7中,可以使用commands模块中的commands.getstatusoutput()来获取一个命令结果和命令状态的元祖,通过读取元祖信息,可以获取相应的信息,命令结果会以2进制保存
但是commands模块,需要在linux/Unix下使用
>>> import commands
>>> a = commands.getstatusoutput('ls')
>>> a
(0, '2.1.py\n2.2.py\n2.3.py\nanaconda-ks.cfg\nDjango-1.7.4\nDjango-1.7.4.tar.gz\ninstall.log\ninstall.log.syslog\nMySQL-python-1.2.5.zip\nPython-2.7.9\nPython-2.7.9.tgz\nPython-3.5.2\nPython-3.5.2.tar\nPython-3.5.2.tgz\nSaltstack\nsetuptools-12.0.5\nsetuptools-12.0.5.tar.gz\nsqlite-autoconf-3080803\nsqlite-autoconf-3080803.tar.gz\nst001\ntestProject\ntestProject.zip\nVMwareTools-8.6.5-621624.tar.gz\nvmware-tools-distrib')
>>> res,commnet = commands.getstatusoutput('ls')
>>> print commnet
2.1.py
2.2.py
2.3.py
anaconda-ks.cfg
Django-1.7.4
Django-1.7.4.tar.gz
install.log
install.log.syslogsubprocess未来会渐渐替换掉os.system和os.swpan模块
 
subprocess.run('','','') #将命令当成参数传递
>>> import subprocess
>>> subprocess.run(['df','-h'])
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/vg_livetech-lv_root
                       12G  4.5G  6.5G  42% /
tmpfs                 3.9G     0  3.9G   0% /dev/shm
/dev/sda1             485M   37M  423M   9% /boot
CompletedProcess(args=['df', '-h'], returncode=0)
此时,可以看到,屏幕打印了执行结果,和命令的执行状态(returncode=0,成功)subprocess.run('',shell=True) #不通过python解析,直接使用系统环境进行解析
>>> subprocess.run('df -h | grep sda1',shell=True)
/dev/sda1             485M   37M  423M   9% /boot
CompletedProcess(args='df -h | grep sda1', returncode=0)
一般,会在需要使用管道‘|’时,会使用shell=True的方式进行调用 
subprocess的常用方法:
#执行命令,返回命令执行状态 , 0 or 非0
>>> res = subprocess.call(["ls", "-l"])>>> print (res)
0
#执行命令,如果命令结果为0,就正常返回,否则抛异常
>>> res = subprocess.check_call(["ls", "-l"])>>> print (res)
0#接收字符串格式命令,返回元组形式,第1个元素是执行状态,第2个是命令结果 
>>> subprocess.getstatusoutput('ls /bin/ls')
(0, '/bin/ls')#接收字符串格式命令,并返回结果
>>> subprocess.getoutput('ls /bin/ls')
'/bin/ls'#执行命令,并返回结果,注意是返回结果,不是打印,下例结果返回给res
>>> res = subprocess.check_output(['ls','-l'])
>>> print(res)
b'total 186688\n-rwxr-xr-x.  1 root root      2051 Apr 21  2016 2.1.py\n-rwxr-xr-x.  1 root root      1496 Apr 22  2016 2.2.py\n-rwxr-xr-x.  1 root root      5498 Apr 26  2016 2.3.py\n我们可以看到,在python3中,所有的信息均是以bytes格式进行保存的
 
其实,在subprocess模块中,底层其实都是封装的subprocess.Popen
>>> subprocess.Popen('ifconfig | grep addr',stdout = subprocess.PIPE,shell=True).stdout.read()
b'Link encap:Ethernet  HWaddr 00:50:56:81:36:54  \n          inet addr:10.253.70.30  Bcast:10.253.70.255  Mask:255.255.255.0\n          inet6 addr: fe80::250:56ff:fe81:3654/64 Scope:Link\n          inet addr:127.0.0.1  Mask:255.0.0.0\n          inet6 addr: ::1/128 Scope:Host\n'
stdout:标准输出stdin:标准输入
stderr:标准错误
>>> res =subprocess.Popen('asdfasdfas',shell=True,stdout = subprocess.PIPE,stderr=subprocess.PIPE)
>>> res.stdout.read()
b''
>>> res.stderr.read()
b'/bin/sh: asdfasdfas: command not found\n'
当命令执行错误时,在stdout中,不会输出信息,而是会在stderr中,输出了错误信息>>> res = subprocess.Popen("sleep 10; echo 'hello world!'",shell=True,stdout = subprocess.PIPE,stdin=subprocess.PIPE,stderr= subprocess.PIPE)
>>> res.poll()
>>> res.poll()
>>> res.poll()
>>> res.poll()
>>> res.poll()
0poll():会去检查子进程是否结束,如果结束,返回执行状态
>>> res = subprocess.Popen("sleep 10; echo 'hello world!'",shell=True,stdout = subprocess.PIPE,stdin=subprocess.PIPE,stderr= subprocess.PIPE)
>>> res.wait()
0
wait():会等待子进程结束,并返回执行状态>>> res = subprocess.Popen('python3',shell=True,stdout=subprocess.PIPE,stdin=subprocess.PIPE,stderr=subprocess.PIPE)
>>> res.stdin.write(b'print(1)')
8
>>> res.stdin.write(b'print(2)')
8
>>> res.stdin.write(b'print(3)')
8
>>> res.stdin.write(b'print(4)')
8
>>> res.stdin.write(b'print(5)')
8
>>> res.communicate()
(b'', b'  File "<stdin>", line 1\n    print(1)print(2)print(3)print(4)print(5)\n                ^\nSyntaxError: invalid syntax\n')
commnuicate(),结束进程