写多个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做了它
  • 如果您不想与系统交互,请注释掉最后两行,但一定要发送一些信号让R脚本退出。
  • spawn()返回一个spawn对象,参见doc这里。
  • 链接地址: http://www.djcxy.com/p/12615.html

    上一篇: write multiple stdin

    下一篇: How to use align