我有app
从stdin
读取内容并在换行后返回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
这可能存在问题吗?
答案 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。