2017-03-01 48 views
1

我已經搜索了一個多小時並在這方面進行了實驗,似乎沒有辦法同時執行'here document'和逐行獲取輸出:Python Popen _with_實時輸入/輸出控制

python = '''var="some character text" 
print(var) 
print(var) 
exit() 
''' 

from subprocess import Popen, PIPE, STDOUT 
import shlex 

def run_process(command): 
    p = Popen(shlex.split(command), stdin=PIPE, stdout=PIPE, stderr=STDOUT) 
    p.stdin.write(python) 
    while True: 
    output = p.stdout.readline() 
    if output == '' and p.poll() is not None: 
     break 
    if output: 
     print output.strip() 
    rc=p.poll() 
    return rc 

run_process("/usr/bin/python") 

上述代碼無限期掛起。是的,這是一條吃蛇尾的蛇,但它只是爲了證明這個概念。

問題是我的子進程需要很長時間才能運行,我需要能夠看到輸出而不用等待幾小時才能確定是否有錯誤。任何提示?謝謝。

+0

你確定它的'stdin.readline'而不是相反 – rakesh

+0

''process.poll的otherway()''應該是一個錯誤(在兩個地方) - 你沒有這個名字的變量。 – jasonharper

+0

不知道我關注。有一個p.stdin.write()調用和一個p.stdout.readline()調用,但沒有發佈代碼中的stdin.readline()。另外,我沒有process.poll() - 我有一個poll()方法的對象p。 – signal7

回答

0

Python解釋器在交互模式和非交互模式下運行時的行爲不同。來自python(1)的手冊頁:

在非交互模式下,整個輸入在執行前被解析。

當然,「整個輸入」是由EOF定界的,並且你的程序永遠不會發送EOF,這就是它掛起的原因。

如果Python的標準輸入爲is a tty,Python將以交互模式運行。您可以使用Ptyprocess庫以tty作爲標準輸入生成一個進程。或者使用Pexpect庫(基於Ptyprocess),它甚至包括用於Python和其他程序的ready-made REPL wrappers


但是如果你的sed替換Python的 - 這當然不具有交互模式 - 該程序仍無法正常工作:

sed = '''this is a foo!\n 
another foo!\n 
''' 

from subprocess import Popen, PIPE, STDOUT 
import shlex 

def run_process(command): 
    p = Popen(shlex.split(command), stdin=PIPE, stdout=PIPE, stderr=STDOUT) 
    p.stdin.write(sed) 
    while True: 
    output = p.stdout.readline() 
    if output == '' and p.poll() is not None: 
     break 
    if output: 
     print output.strip() 
    rc=p.poll() 
    return rc 

run_process("/bin/sed -e 's/foo/bar/g'") 

這是由不同的問題引起:輸出在sed中緩衝。有些程序可以選擇禁用緩衝。尤其是,這兩個sed和Python中有一個-u選項,它解決了這個問題:

run_process("/bin/sed -ue 's/foo/bar/g'") 
+0

謝謝你指出。明天我會用'cat'重新測試它的行爲是否有所不同。 – signal7

+0

這解決了我的問題。如果我在p.stdin.write()之後調用p.stdin.close(),現在它的行爲如預期。謝謝。 – signal7