python调用Shell脚本,有两种方法:os.system(cmd)或os.popen(cmd),前者返回值是脚本的退出状态码,后者的返回值是脚本执行过程中的输出内容。所以说一般我们认为popen更加强大
os.system(cmd):
该方法在调用完shell脚本后,返回一个16位的二进制 数,低位为杀死所调用脚本的信号号码,高位为脚本的退出状态码,即脚本中“exit 1”的代码执行后,os.system函数返回值的高位数则是1,如果低位数是0的情况下,则函数的返回值是0×100,换算为10进制得到256。
os.popen(cmd):
这种调用方式是通过管道的方式来实现,函数返回一个file-like的对象,里面的内容是脚本输出的内容(可简单理解为echo输出的内容)。
实例如下:
1 import numpy
2 import os
3 t=os.popen('ls')
4 print t.read()
5 t=os.system('ls')
6 print t
server.py
setup.py
t
test
test.c
test.nja
test.o
0
-----------------------------------------------------我是分割线---------------------------------------------------------------------------------------------------------
受@赵锐指教,subprocess的Popen更实用。于是赶紧学习了一下
官方指南:https://docs.python.org/2/library/subprocess.html
官方也建议用这个替代(当然unix用户还有个更新的subprocess32)
这个模块粗略的看一下主要是启用另一个线程,并可获取输入,输出以及错误信息等,并提供了subprocess.Popen以及他的几个封装函数
先介绍下封装的函数
一、subprocess.call
subprocess.call (*popenargs , **kwargs )
执行命令,并等待命令结束,再返回子进程的返回值。参数同Popen。我暂时的理解就是这个是加上了同步的popen。
二、subprocess.check_call
subprocess.check_call (*popenargs , **kwargs )
执行上面的call命令,并检查返回值,如果子进程返回非0,则会抛出CalledProcessError异常,这个异常会有个returncode 属性,记录子进程的返回值。
三、check_output()
执行程序,并返回其标准输出.
而Popen则用起来更广泛,用起来和call一样,只是如果要同步要自己加上wait
借鉴一下属性
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信息。
关于subprocess的安全性:
不像其他的popen函数,不会直接调用/bin/sh来解释命令,也就是说,命令中的每一个字符都会被安全地传递到子进程里。
这里着重介绍一下怎么用这个替换原本的几个库
一、替换shell命令
output=`mycmd myarg`
# 替换为
output = check_output(["mycmd", "myarg"]
二、替换shell管道
output=`dmesg | grep hda`
# 替换为
p1 = Popen(["dmesg"], stdout=PIPE)
p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE)
p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits.
output = p2.communicate()[0]
三、替换os.system()
status = os.system("mycmd" + " myarg")
# 替换为
status = subprocess.call("mycmd" + " myarg", shell=True)
通常并不需要用shell来调用程序。
用subprocess可以更方便地得到子程序的返回值。
其实,更真实的替换是:
try:
retcode = call(“mycmd” + ” myarg”, shell=True)
if retcode < 0:
print >>sys.stderr, “Child was terminated by signal”, -retcode
else:
print >>sys.stderr, “Child returned”, retcode
except OSError, e:
print >>sys.stderr, “Execution failed:”, e
代替os.spawn系列
P_NOWAIT的例子
pid = os.spawnlp(os.P_NOWAIT, “/bin/mycmd”, “mycmd”, “myarg”)
等效于
pid = Popen(["/bin/mycmd", "myarg"]).pid
P_WAIT的例子
retcode = os.spawnlp(os.P_WAIT, “/bin/mycmd”, “mycmd”, “myarg”)
等效于
retcode = call(["/bin/mycmd", "myarg"])
Vector的例子
os.spawnvp(os.P_NOWAIT, path, args)
等效于
Popen([path] + args[1:])
关于环境变量的例子
os.spawnlpe(os.P_NOWAIT, “/bin/mycmd”, “mycmd”, “myarg”, env)
等效于
Popen(["/bin/mycmd", "myarg"], env={“PATH”: “/usr/bin”})
代替
os.popen()
,
os.popen2()
,
os.popen3()
:
pipe = os.popen(“cmd”, ‘r’, bufsize)
等效于
pipe = Popen(“cmd”, shell=True, bufsize=bufsize, stdout=PIPE).stdout