保持管道打开过程

时间:2011-06-14 16:13:29

标签: python subprocess pipe popen

我有appstdin读取内容并在换行后返回stdout

一个简单(愚蠢)的例子:

$ app
Expand[(x+1)^2]<CR>
x^2 + 2*x + 1
100 - 4<CR>
96

打开和关闭app需要大量的初始化和清理(它是计算机代数系统的接口),因此我希望将其保持在最低限度。

我想在Python中打开一个用于此过程的管道,将字符串写入其stdin并从stdout读出结果。 Popen.communicate()不起作用,因为它关闭文件句柄,需要重新打开管道。

我尝试过与此相关的问题: Communicate multiple times with a process without breaking the pipe?但我不确定如何等待输出。也很难先验地知道app完成处理手头输入需要多长时间,所以我不想做任何假设。我想我的大部分困惑来自于这个问题:Non-blocking read on a subprocess.PIPE in python其中指出混合高级和低级函数不是一个好主意。

修改: 对不起,我之前没有提供任何代码,被打断了。这是我到目前为止所尝试过的,它似乎有效,我只是担心出现问题而不被注意:

from subprocess import Popen, PIPE
pipe = Popen(["MathPipe"], stdin=PIPE, stdout=PIPE)         
expressions = ["Expand[(x+1)^2]", "Integrate[Sin[x], {x,0,2*Pi}]"] # ...                                                                                        
for expr in expressions:
    pipe.stdin.write(expr)                                                        
    while True:                                                                         
        line = pipe.stdout.readline()                                                    
        if line != '':     
            print line  
        # output of MathPipe is always terminated by ';'                                                                                                                         
        if ";" in line:                                                                  
            break                                                                       

这可能存在问题吗?

2 个答案:

答案 0 :(得分:3)

使用子进程,您无法可靠地执行此操作。您可能希望查看使用pexpect库。这不适用于Windows - 如果您使用的是Windows,请尝试winpexpect

另外,如果您正在尝试使用Python编写数学内容,请查看SAGE。他们在与其他开源数学软件接口方面做了很多工作,所以他们有可能已经完成了你想要做的事情。

答案 1 :(得分:2)

也许您可以将stdin=subprocess.PIPE作为参数传递给subprocess.Popen。这将使进程'stdin可用作一般文件对象:

import sys, subprocess

proc = subprocess.Popen(["mathematica <args>"], stdin=subprocess.PIPE, 
                        stdout=sys.stdout, shell=True)
proc.stdin.write("Expand[ (x-1)^2 ]") # Write whatever to the process
proc.stdin.flush()                    # Ensure nothing is left in the buffer
proc.terminate()                      # Kill the process

这会将子进程的输出直接指向你的python进程'stdout。如果您需要先阅读输出并进行一些编辑,也可以这样做。查看http://docs.python.org/library/subprocess.html#popen-objects