簡體   English   中英

Python子進程——寫多個stdin

[英]Python subprocess - write multiple 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 腳本)退出並出現錯誤,表示子處理沒有收到預期輸入的輸入,因此終止。

NB - 在一個完美的世界中,我只會直接通過 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('myfirstinput\n')
p.stdin.write('q\n')

stdout, stderr = p.communicate()

print '---STDOUT---'
print stdout
print '---STDERR---'
print stderr
print '---'

討論

  • 我不使用shell=True並且它似乎可以使用我的假 R腳本,因為我的系統中沒有安裝 R。 您可能需要也可能不需要它。
  • 我更喜歡將命令行分解為一個字符串列表,如圖所示,但是像r --nosave這樣的單個字符串也可以工作; 只是不要同時做它們。
  • 不要忘記stdin.write()不會寫入換行符\\n ,您必須自己提供。

更新

我的第一次嘗試沒有成功,我希望第二次嘗試更接近。 正如 JF Sebastian 所建議的,您可能想要使用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對象,請參閱此處的文檔。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM