写多个stdin
我需要打开一个R脚本并为其提供由单独的python脚本制定的输入。 subprocess
模块似乎是一个很好的方法来做到这一点。
虽然我遇到了一些令人费解的结果,也就是说我可以通过p.stdin
显然只写一次。 这是我到目前为止:
from subprocess import Popen, PIPE, STDOUT
p = Popen(['r --no-save'],stdin=PIPE,stdout=PIPE,stderr=PIPE,shell=True)
p.stdin.write("source('myrscript.R')n")
p.stdin.write('myfirstinput')
当我运行这段代码时,会发生什么情况是stdin.write()
的第一个实例按预期执行(并打开了我的R脚本),但第二行什么也不做,并且子进程(实际上是R脚本)退出并出现错误,表明子处理没有收到输入,因为输入是预期的,因此终止。
注意 - 在完美的世界中,我只是直接通过R进行交互,但是这个特殊的脚本需要复杂的输入,不能直接输入实际用途。 另外,rpy / rpy2不是一个选项,因为此脚本的最终用户不一定有权访问该模块或其依赖项。 rscript
是一种选择(出于许多原因,但主要是由于最终用户R配置的可变性)。
最后, p.communicate
不是一种选择,因为显然这将在写完后关闭过程,并且我需要保持打开状态。
提前致谢
你需要的是调用.communicate()
:
from subprocess import Popen, PIPE, STDOUT
p = Popen(
['r', '--nosave'],
stdin=PIPE,
stdout=PIPE,
stderr=PIPE)
p.stdin.write("source('myrscript.R')n")
p.stdin.write('myfirstinputn')
p.stdin.write('qn')
stdout, stderr = p.communicate()
print '---STDOUT---'
print stdout
print '---STDERR---'
print stderr
print '---'
讨论
shell=True
,它似乎与我的假R脚本一起工作,因为我的系统中没有安装R。 你可能会也可能不需要它。 r --nosave
这样的单个字符串也可以工作; 只是不要同时做这两件事。 stdin.write()
不会写入新行字符n
,您必须自己提供。 更新
我的第一次尝试不合格,我希望第二次尝试接近。 正如JF塞巴斯蒂安所建议的那样,您可能需要使用pexpect
:
import pexpect
import sys
if __name__ == '__main__':
prompt = '> ' # Don't know what the R prompt looks like
lines = ['one', 'two', 'three']
r = pexpect.spawn('r --no-save', logfile=sys.stdout)
for line in lines:
r.expect(prompt)
r.sendline(line)
# If you want to interact with your script, use these two lines
# Otherwise, comment them out
r.logfile = None # Turn off logging to sys.stdout
r.interact()
讨论
pexpect
。 我用pip install pexpect
做了它 spawn()
返回一个spawn
对象,参见doc这里。 上一篇: write multiple stdin
下一篇: How to use align