保持与进程的管道保持打开状态
我有一个app
,它从stdin
读取数据,然后在换行后把结果返回到stdout
。
这里有个简单(其实有点傻)的例子:
$ app
Expand[(x+1)^2]<CR>
x^2 + 2*x + 1
100 - 4<CR>
96
打开和关闭这个app
需要很多初始化和清理工作(它是一个计算代数系统的接口),所以我想尽量减少这个过程。
我想在Python中打开一个管道,给它的stdin
写入字符串,然后从stdout
读取结果。Popen.communicate()
不适合这个,因为它会关闭文件句柄,这样就需要重新打开管道。
我试过类似于这个相关问题的做法:
如何在不破坏管道的情况下多次与进程通信?但我不太确定怎么等待输出。而且很难提前知道app
处理当前输入需要多长时间,所以我不想做任何假设。我想我大部分的困惑来自这个问题: 在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 个回答
你可以把 stdin=subprocess.PIPE
作为参数传给 subprocess.Popen
。这样做会让这个进程的输入变成一个像文件一样的对象,方便你使用:
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 进程的输出。如果你需要先读取输出并进行一些处理,也是可以的。可以查看一下 http://docs.python.org/library/subprocess.html#popen-objects。
使用subprocess这个工具,你可能无法可靠地完成某些操作。你可以考虑使用pexpect这个库。不过,这个库在Windows系统上不太适用。如果你是在Windows上,可以试试winpexpect。
另外,如果你想在Python中做一些数学相关的事情,可以看看SAGE。他们在与其他开源数学软件的对接方面做了很多工作,所以很有可能他们已经实现了你想要的功能。