三、subprocess模块
1、subprocess.run()
?
1
2
3
4
5
6
7
8
9
10
11
12
13
>>> import subprocess
# python 解析则传入命令的每个参数的列表
>>> subprocess.run(["df","-h"])
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/VolGroup-LogVol00
289G 70G 204G 26% /
tmpfs 64G 0 64G 0% /dev/shm
/dev/sda1 283M 27M 241M 11% /boot
CompletedProcess(args=['df', '-h'], returncode=0)
# 需要交给Linux shell自己解析,则:传入命令字符串,shell=True
>>> subprocess.run("df -h|grep /dev/sda1",shell=True)
/dev/sda1 283M 27M 241M 11% /boot
CompletedProcess(args='df -h|grep /dev/sda1', returncode=0)
2、subprocess.call()
执行命令,返回命令的结果和执行状态,0或者非0
?
1
2
3
4
5
6
7
8
9
10
>>> res = subprocess.call(["ls","-l"])
总用量 28
-rw-r--r-- 1 root root 0 6月 16 10:28 1
drwxr-xr-x 2 root root 4096 6月 22 17:48 _1748
-rw-------. 1 root root 1264 4月 28 20:51 anaconda-ks.cfg
drwxr-xr-x 2 root root 4096 5月 25 14:45 monitor
-rw-r--r-- 1 root root 13160 5月 9 13:36 npm-debug.log
# 命令执行状态
>>> res
0
3、subprocess.check_call()
执行命令,返回结果和状态,正常为0 ,执行错误则抛出异常
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
>>> subprocess.check_call(["ls","-l"])
总用量 28
-rw-r--r-- 1 root root 0 6月 16 10:28 1
drwxr-xr-x 2 root root 4096 6月 22 17:48 _1748
-rw-------. 1 root root 1264 4月 28 20:51 anaconda-ks.cfg
drwxr-xr-x 2 root root 4096 5月 25 14:45 monitor
-rw-r--r-- 1 root root 13160 5月 9 13:36 npm-debug.log
0
>>> subprocess.check_call(["lm","-l"])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib64/python2.7/subprocess.py", line 537, in check_call
retcode = call(*popenargs, **kwargs)
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
4、subprocess.getstatusoutput()
接受字符串形式的命令,返回 一个元组形式的结果,第一个元素是命令执行状态,第二个为执行结果
?
1
2
3
4
5
6
#执行正确
>>> subprocess.getstatusoutput('pwd')
(0, '/root')
#执行错误
>>> subprocess.getstatusoutput('pd')
(127, '/bin/sh: pd: command not found')
5、subprocess.getoutput()
接受字符串形式的命令,放回执行结果
?
1
2
>>> subprocess.getoutput('pwd')
'/root'
6、subprocess.check_output()
执行命令,返回执行的结果,而不是打印
?
1
2
3
>>> res = subprocess.check_output("pwd")
>>> res
b'/root
' # 结果以字节形式返回
四、subprocess.Popen()
其实以上subprocess使用的方法,都是对subprocess.Popen的封装,下面我们就来看看这个Popen方法。
1、stdout
标准输出
?
1
2
3
4
>>> res = subprocess.Popen("ls /tmp/yum.log", shell=True, stdout=subprocess.PIPE) # 使用管道
>>> res.stdout.read() # 标准输出
b'/tmp/yum.log
'
res.stdout.close() # 关闭
2、stderr
标准错误
?
1
2
3
4
5
6
7
8
>>> import subprocess
>>> res = subprocess.Popen("lm -l",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
# 标准输出为空
>>> res.stdout.read()
b''
#标准错误中有错误信息
>>> res.stderr.read()
b'/bin/sh: lm: command not found
'
注意:上面的提到的标准输出都为啥都需要等于subprocess.PIPE,这个又是啥呢?原来这个是一个管道,这个需要画一个图来解释一下:
4、poll()
定时检查命令有没有执行完毕,执行完毕后返回执行结果的状态,没有执行完毕返回None
?
1
2
3
4
5
6
7
>>> res = subprocess.Popen("sleep 10;echo 'hello'",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
>>> print(res.poll())
None
>>> print(res.poll())
None
>>> print(res.poll())
0
5、wait()
等待命令执行完成,并且返回结果状态
?
1
2
3
4
>>> obj = subprocess.Popen("sleep 10;echo 'hello'",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
>>> obj.wait()
# 中间会一直等待
0
6、terminate()
结束进程
?
1
2
3
4
5
import subprocess
>>> res = subprocess.Popen("sleep 20;echo 'hello'",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
>>> res.terminate() # 结束进程
>>> res.stdout.read()
b''
7、pid
获取当前执行子shell的程序的进程号
?
1
2
3
4
import subprocess
>>> res = subprocess.Popen("sleep 5;echo 'hello'",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
>>> res.pid # 获取这个linux shell 的 进程号
2778
subprocess.Popen():
class Popen(args, bufsize=0,
executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None,
close_fds=False, shell=False, cwd=None, env=None,
universal_newlines=False, startupinfo=None, creationflags=0)
在一些复杂场景中,我们需要将一个进程的执行输出作为另一个进程的输入。在另一些场景中,我们需要先进入到某个输入环境,然后再执行一系列的指令等。这个时候我们就需要使用到suprocess的Popen()方法。该方法有以下参数:
args:shell命令,可以是字符串,或者序列类型,如list,tuple。
bufsize:缓冲区大小,可不用关心
stdin,stdout,stderr:分别表示程序的标准输入,标准输出及标准错误
shell:与上面方法中用法相同
cwd:用于设置子进程的当前目录
env:用于指定子进程的环境变量。如果env=None,则默认从父进程继承环境变量
universal_newlines:不同系统的的换行符不同,当该参数设定为true时,则表示使用
作为换行符
Popen方法
1、Popen.poll():用于检查子进程是否已经结束。设置并返回returncode属性。
2、Popen.wait():等待子进程结束。设置并返回returncode属性。
3、Popen.communicate(input=None):与子进程进行交互。向stdin发送数据,或从stdout和stderr中读取数据。可选参数input指定发送到子进程的参数。Communicate()返回一个元组:(stdoutdata,
stderrdata)。注意:如果希望通过进程的stdin向其发送数据,在创建Popen对象的时候,参数stdin必须被设置为PIPE。同样,如果希望从stdout和stderr获取数据,必须将stdout和stderr设置为PIPE。
4、Popen.send_signal(signal):向子进程发送信号。
5、Popen.terminate():停止(stop)子进程。在windows平台下,该方法将调用Windows API TerminateProcess()来结束子进程。
6、Popen.kill():杀死子进程。
7、Popen.stdin:如果在创建Popen对象是,参数stdin被设置为PIPE,Popen.stdin将返回一个文件对象用于策子进程发送指令。否则返回None。
8、Popen.stdout:如果在创建Popen对象是,参数stdout被设置为PIPE,Popen.stdout将返回一个文件对象用于策子进程发送指令。否则返回None。
9、Popen.stderr:如果在创建Popen对象是,参数stdout被设置为PIPE,Popen.stdout将返回一个文件对象用于策子进程发送指令。否则返回None。
10、Popen.pid:获取子进程的进程ID。
11、Popen.returncode:获取进程的返回值。如果进程还没有结束,返回None。
12、subprocess.call(*popenargs, **kwargs):运行命令。该函数将一直等待到子进程运行结束,并返回进程的returncode。文章一开始的例子就演示了call函数。如果子进程不需要进行交互,就可以使用该函数来创建。
13、subprocess.check_call(*popenargs,
**kwargs):与subprocess.call(*popenargs,
**kwargs)功能一样,只是如果子进程返回的returncode不为0的话,将触发CalledProcessError异常。在异常对象中,包括进程的returncode信息。