python执行系统命令的方法:os.system(), os.popen(), subprocess.Popen()
一、os.system方法
优点:使用方法简单。
缺点:1)返回值只包含命令执行状态,不包含命令输出。2)阻塞
1)返回值 执行操作系统的命令,将结果输出到屏幕,只返回命令执行状态(0:成功,非 0 : 失败) >>> result = os.system('pwd') /root >>> result 0 2)阻塞 在执行os.system函数的时候通常会阻塞它的调用者,等待所启动的命令行程序退出。 在Linux平台上 只需要在命令末尾加上shell后台运算符&即可。
二、os.popen方法
执行操作系统的命令,会将结果保存在file对象当中,可以用read()、readlines()等
方法读取出来
优点:执行简单,返回结果包含命令的输出。
import os result = os.popen('cat /etc/passwd') print(result.read()) root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
三、commands模块
关于 commands 的说明:
- python 3.0 之后移除此命令,使用 subprocess代替;
- python 3.x 使用 subprocess 创建一个新进程;
四、subprocess模块
Subprocess是一个功能强大的子进程管理模块,是替换
- os.system
- os.spawn*
- os.popen*
- popen2.*
- commands.*
等方法的一个模块。
当执行命令的参数或者返回中包含了中文文字,那么建议使用subprocess。
1、subprocess.run()
1.1、 python 解析传入命令的每个参数的列表
1.2、需要交给Linux shell自己解析,则:传入命令字符串,shell=True
>>> res = subprocess.run("cd",shell=True,stdout=subprocess.PIPE) >>> res.stdout b'C:\\Users\\wangwuhui\\Desktop\r\n'
2、subprocess.call()
相当于os.system()
3、subprocess.check_call()
执行命令,返回结果和状态,正常为0 ,执行错误则抛出异常
4、subprocess.getstatusoutput()
接受字符串形式的命令,返回 一个元组形式的结果,第一个元素是命令执行状态,第二个为执行结果
4.1、执行正确
>>> result = subprocess.getstatusoutput("pwd") >>> result (0, '/root')
4.2、执行错误
>>> result = subprocess.getstatusoutput("pwdd") >>> result (127, '/bin/sh: pwdd: command not found')
5、subprocess.getoutput()
接受字符串形式的命令,返回执行结果
5.1、执行命令正常
>>> result = subprocess.getoutput("pwd") >>> result '/root'
5.2、执行命令出错
>>> result = subprocess.getoutput("pwdd") >>> result '/bin/sh: pwdd: command not found' >>>
6、subprocess.check_output()
7、subprocess.Popen()
其实前面subprocess使用的方法,都是对subprocess.Popen的封装,下面我们就来看看这个Popen方法。
7.1、stdout
标准输出
>>> res
=
subprocess.Popen(
"ls /tmp/yum.log"
, shell
=
True
, stdout
=
subprocess.PIPE)
# 使用管道
>>> res.stdout.read()
# 标准输出
b
'/tmp/yum.log\n'
res.stdout.close()
# 关闭
7.2、stderr
标准错误
>>>
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\n'
注意:上面的提到的标准输出都为啥都需要等于subprocess.PIPE,这个又是啥呢?原来这个是一个管道,这个需要画一个图来解释一下
7.3、poll()
定时检查命令有没有执行完毕,执行完毕后返回执行结果的状态,没有执行完毕返回None
>>> 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
7.4、wait()
等待命令执行完成,并且返回结果状态
>>> obj = subprocess.Popen("sleep 10;echo 'hello'",shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE) >>> obj.wait() # 中间会一直等待 0
7.5、terminate()
结束进程
import
subprocess
>>> res
=
subprocess.Popen(
"sleep 20;echo 'hello'"
,shell
=
True
,stdout
=
subprocess.PIPE,stderr
=
subprocess.PIPE)
>>> res.terminate()
# 结束进程
>>> res.stdout.read()
b''
7.6、pid
获取当前执行子shell的程序的进程号
import
subprocess
>>> res
=
subprocess.Popen(
"sleep 5;echo 'hello'"
,shell
=
True
,stdout
=
subprocess.PIPE,stderr
=
subprocess.PIPE)
>>> res.pid
# 获取这个linux shell 的 进程号
2778
7.7、communicate
该方法可用来与进程进行交互,比如发送数据到stdin,从stdout和stderr读取数据,直到到达文件末尾。
例子1:子进程中使用录屏软件。
#coding:utf-8 import time import os import datetime import subprocess def live_video(): file_name = datetime.datetime.now().strftime('%Y-%m-%d-%H-%M-%S.mp4')
# 开启录屏 live_video = subprocess.Popen('ffmpeg -f gdigrab -i desktop -vcodec libx264 -pix_fmt yuv420p {} -y'.format(file_name),shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE) time.sleep(10) # 录制10秒 live_video.stdin.write('q'.encode("GBK")) # 发送命令,停止录屏 live_video.communicate() # 发送数据到标准输入 live_video()
例子2:子进程中使用Python
print("***Popen对象stdin写入功能:使用communicate输出") p4 = subprocess.Popen(["python"], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) p4.stdin.write("print('hello')") output = p4.communicate() print(output) # 结果:('hello\n', '')
例子3:子进程中切换账户
p4 = subprocess.Popen("/opt/work/plsh/plsh",stdout=subprocess.PIPE,stdin=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True,shell=True) p4.stdin.write("test\n") # 输入用户名 p4.stdin.write("lalala.test\n") # 输入密码 p4.stdin.write("show capture\n") #切换账户后,执行命令 output = p4.communicate()[0]
更多例子参考:
https://www.jianshu.com/p/430c411160f8