在一些需求中,免不了要执行linux的shell脚本,可以使用subprocess模块。在subprocess模块中启动子进程,最简单的方式就是使用便利函数。当这些便利函数不能满足需求时,再使用底层的Popen类。
call函数将运行由args参数指定的命令直到命令结束。call函数的返回值是命令的退出状态码,工程师可以通过退出状态码判断命令是否执行成功。
import subprocess
subprocess.call(['ls','-l'])
subprocess.call("exit 1",shell=True)
call函数执行的外部命令以一个字符串列表的形式进行传递,如果设置了shell为True,则可以使用一个字符串命令,而不是一个字符串列表来运行子进程。如果设置了shell为True,Python将先运行一个shell,再用这个shell来解释整个字符串。
check_call函数的作用与call函数类似,区别在于异常情况下返回的形式不同。对于call函数,工程师通过捕获call命令的返回值判断命令是否执行成功,如果成功返回0,否则返回非0。对于check_call函数,如果执行命令成功,返回0,如果执行失败,抛出subprocess.CalledProcessError异常。
call和check_call函数直接将命令的输出结果输出到命令行终端,这种返回结果的形式很有可能不是你想要的。在实际工作过程中,一般会对获取命令的结果进行进一步的处理,或者将命令的输出打印到日志文件中。
import subprocess
output = subprocess.check_output(['ls','-l'], stderr=subprocess.STDOUT)
print(output)
check_output函数通过返回值来返回命令的执行结果,显然无法像call函数一样通过返回退出状态码表示异常情况。因此, check_output函数通过抛出一个subprocess.CalledProcessError异常来表示命令执行出错。
默认情况下,check_output命令只会捕获命令的标准输出。如果想捕获命令的错误输出,需要将错误输出重定向到标准输出。
subprocess模块提供的便利函数都是对Popen类的封装,当便利函数无法满足业务的需求时,也可以直接使用Popen类。Popen类更具有灵活性,通过它能处理更多复杂的情况。
1、wait:等待子进程结束;
2、poll:检查子进程状态;
3、kill:给子进程发送SIGKILL信号终止子进程;
4、send_signal:向子进程发送信号;
5、terminate:给子进程发送SIGTERM信号终止子进程;
6、communicate:与子进程交互。
import subprocess
def execute_cmd(cmd):
p = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
if p.returncode != 0:
return p.returncode, stderr
return p.returncode, stdout
print(execute_cmd("ls"))