subprocess模块记录

由于实际需求,需要用到subprocess模块进行调用exe程序,并向子进程输入一些数据。在实际操作中遇到了不少困惑,记录一下。python版本为2.6,并已配置好python的环境变量。

首先看一个简单的demo。

以下是test.py的内容,主要是从IO获取两次输入,然后打印显示输入信息。

def main():
    a = raw_input('a:')
    b = raw_input('b:')
    print 'a=' + a
    print 'b=' + b
pass

if __name__ == "__main__":
    main()

以下是testforsubprocess.py的内容,以创建一个test.py运行实例作为子进程,并往子进程的输入端输入1和qq两个字符串,最后再获取输出端的信息。

import subprocess

def myTest(): 
    cmd = 'python test.py'
    if cmd != None:
        c =  cmd
        print c
        p = subprocess.Popen(c,shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
        p.stdin.write('1\n')
        p.stdin.write('qq\n')
        while True:
            buff = string.strip(p.stdout.readline())
            if buff == '' :
                print '======================='
                print 'completed'
                print '======================='
                break
            else:
                print buff
        passpass

myTest()

运行结果如下:

python test.py
a:b:a=1
b=qq
=======================
install completed
=======================

 

class subprocess.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)

在 subprocess.Popen()方法中,这个例子中最主要的参数是args、stdin和stdout。args给定的是一个可执行的命令,这里注 意了,python环境变量要配置好。而stdin和stdout就是接下来的重点了。在这个例子中,stdin和stdout都设置为PIPE,输入和 输出都能够正常运行。在参考了网络上诸多的例子之后,我才明白,stdin和stdout也可以设置为文件对象。如下所示:

def myTest(): 
    cmd = 'python test.py'
    if cmd != None:
        c =  cmd
        print c
        myinput = open('myinput.in')
        myoutput = open('myoutput.out','w')
        p = subprocess.Popen(c,shell=True,stdin=myinput,stdout=myoutput,stderr=subprocess.PIPE)
pass

输 入端变成了myinput.in,myinput.in文件就两行数据,一行是1,一行是qq;输出端变成了myoutput.out。程序依旧正常完 成。查看myoutput.out文件,也是两行信息,a:b:a=1和b=qq。单单只改变stdin为文件,或者单单只改变stdout为文件,程序 也能正常完成。如此就说明了设置为文本与PIPE是类似的。

根据官网文档提示:

Warning Use communicate() rather than .stdin.write, .stdout.read or .stderr.read to avoid deadlocks due to any of the other OS pipe buffers filling up and blocking the child process.

应该尽可能的使用communicate(),故尝试一下。

def myTest(): 
    cmd = 'python test.py'
    if cmd != None:
        c =  cmd
        print c
        p = subprocess.Popen(c,shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
        output = p.communicate(input='1\nqq\n')[0]
        print output
pass

输出信息与之前的一致,如此方明白输入信息可以一并和在一起输入。就如同第一个小例子的p.stdin.write('1\n')和p.stdin.write('qq\n')可以一并写为p.stdin.write('1\nqq\n')。

如此看起来,似乎subprocess应用起来还是比较简单的。而实际中,让小弟我无可奈何。

由 于我想调用的exe程序并非如例子中如此简单,因此类似的照猫画虎已经不管用了,总是造成死锁,让我很是郁闷。最后才有一点点感悟,调用的exe程序,第 一个输入也只是简单的判断,但之后的输入对于程序而言可能需要几十毫秒的运行时间,从我手动执行该exe程序可以感受到。最后尝试了在每次输入时加入 time.sleep()来暂时解决该现象。

import subprocess
import time

def myTest(): 
    cmd = 'exe程序的绝对路径'
    if cmd != None:
        c =  cmd
        print c
        p = subprocess.Popen(c,shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
        p.stdin.write('input message\n')
        time.sleep(0.5)
        p.stdin.write('input message\n')
        time.sleep(0.5)
        p.stdin.write('input message\n')
        time.sleep(0.5)
        while True:
            buff = string.strip(p.stdout.readline())
            if buff == '' :
                print '======================='
                print 'completed'
                print '======================='
                break
            else:
                print buff
        passpass

myTest()

subprocess的确是一个很强大的模块,目前尚有很多不解之处,先记录之。待有所突破,继续更新。

posted @ 2013-09-26 17:34  miteng  阅读(365)  评论(0编辑  收藏  举报