您的位置:首页 > 编程语言 > Python开发

python-subprocess创建附加进程

2014-11-04 09:43 381 查看
如果你是一名Unix/Linux系统管理员,那么对进程进行处理将会是工作的主要内容。你需要知道启动脚本、运行等级、守护进程、长时间运行的进程以及一大堆相关问题。所幸的是,Python处理进程相当容易。从Python2.4开始,Subprocess已经成为一站式模块,允许你派生出新的进程,并且与标准输入、标准输出以及标准错误输出进行会话。与进程会话是处理进程的一方面,理解如何部署和管理长时间运行的进程也是很重要的。

子进程

Python的Subprocess或许是单一的最重要的模块,它对于shelling out具有统一API。Python中的子进程负责处理下列事物:派生新的进程连接标准输入、连接标准输出、连接错误流、侦听返回码。子进程的一个简单示例:

import subprocess
subprocess.call(['df','-k'], shell = True)


subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False):父进程等待子进程完成,返回执行状态码。shell
= True表示在shell中执行命令,不要将stdout=PIPE或者stdin=PIPE用于该函数,否则可能会因子进程大量输出而导致死锁。

错误处理

call()的返回值是程序的退出码,调用者都要负责解释这个返回值来检测错误。check_call()函数的工作类似于call(),除了检查退出码外,如果发生了错误,则会产生一个CalledProcessError异常。
try:
subprocess.check_call(['false'])
except subprocess.CalledProcessError as err:
print 'ERROR:', err

Subprocess捕获标准输出

某些情况下只对系统调用感兴趣,而不关心标准输出。在这种情况下,经常需要禁止Subprocess.call的标准输出,只需将输出定位到/dev/null中即可:

import subprocess
subprocess.call("ping -c 3 www.baidu.com", shell = True, stdout = open('/dev/null'), stderr = subprocess.STDOUT)


如果对shell命令的输出不感兴趣,只是希望程序被运行,可典型的使用Subprocess.call,如果需要得到子进程的运行结果,则可以用subprocess.Popen。在subprocess.call与subprocess.Popen之间,存在一个非常大的差异。subprocess.call会封锁对时间的等待(即会卡住等待子进程运行结束),而subprocess.Popen不会。

p = subprocess.Popen('df -h", shell = True, stdout = subprocess.PIPE)
out = p.stdout.read()
print out

subprocess.check_output()也得到标准输出。
subprocess.check_output(args, *, stdin=None, stderr=None, shell=False,universal_newlines=False):父进程等待子进程完成,返回子进程向标准输出的输出结果,检查退出信息,如果returncode不为0,则举出错误subprocess.CalledProcessError,该对象包含有returncode属性和output属性,output属性为标准输出的输出结果,可用try…except…来检查。
try:
p = subporcess.check_output(['du -sh','/home/'], shell = True)
print p
except  subprocess.CalledProcessError as err:
print 'ERROR:',err


使用Subprocess与标准输入进行通信

p = subprocess.Popen("wc -c", shell = True, stdin=subprocess.PIPE)
p.communicate("charactersinword")


输出:16,具有相同功能的Bash代码为:
$ echo charactersinword | wc -c
p.communicate会一直等到进程退出,并将标准输出和标准错误输出返回,这样就可以得到子进程的输出了,另一个例子为:
p = subprocess.Popen('ls', shell = True, stdout = subprocess.PIPE)
stdoutput,stderrput = p.communicate('/home/zoer')
print stdoutput
print stderrput
在Bash中可以用管道连接多个命令,比如:
cat /etc/passwd | grep 0:0 | cut -d ':' -f 7

利用subprocess也可连接多个命令,实现相同的功能:
p1 = subprocess.Popen("cat /etc/passwd", shell = True, stdout = subprocess.PIPE)
p2 = subprocess.Popen("grep 0:0", shell = True, stdin = p1.stdout, stdout = subprocess.PIPE)
p3 = subprocess.Popen("cut -d ':' -f 7", shell = True, stdin = p2.stdout, stdout = subprocess.PIPE)
print p3.stdout.read()

Popen()方法:

Popen.poll():检查子进程是否结束,设置并返回return code属性
Popen.wait(): 等待子进程结束,设置并返回return code属性
Popen.communicate(input=None): 与子进程进行交互,或从stdout和stderr中读取数据。可选参数input指定发送到子进程的参数。Communicate()返回一个元组:(stdoutdata, stderrdata)。注意:如果希望通过进程的stdin向其发送数据,在创建Popen对象的时候,参数stdin必须被设置为PIPE。同样,如果希望从stdout和stderr获取数据,必须将stdout和stderr设置为PIPE。
Popen.send_signal(signal): 向子进程发送信号
Popen.terminate(): 停止(stop)子进程
Popen.kill(): 杀死(kill)子进程
Popen.pid: 获取子进程的ID
Popen.returncode: 获取返回值,如果进程还没结束,就返回None
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: