2012-09-28 177 views
1

我有一個腳本parent.py試圖從Python中的子進程sub.py讀取標準輸出。從刷新和未刷新緩衝區讀取

parent.py

#!/usr/bin/python 
import subprocess 
p = subprocess.Popen("sub.py", stdout=subprocess.PIPE) 
print p.stdout.read(1) 

而且子,sub.py

#!/usr/bin/python 
print raw_input("hello world!") 

我希望運行parent.py從中打印的 'H' 「世界,你好!」。其實,它掛起。我只能通過將-u添加到sub.py的she-bang line來獲得預期的行爲。

這讓我感到困惑,因爲當sub.py直接從shell運行時,-u開關沒有任何區別; shell不知何故知道未刷新的輸出流,與parent.py不同。

我的目標是運行一個C程序作爲子進程,所以我將無法控制是否刷新標準輸出。它是如何比Python運行subprocess.Popen同樣的東西更好地訪問進程的stdout?我能否從C程序中讀取不刷新緩衝區的stdout流?

編輯:

這裏是基於korylprince的評論更新的例子...

## capitalize.sh ## 
#!/bin/sh 

while [ 1 ]; do 
    read s 
    echo $s | tr '[:lower:]' '[:upper:]' 
done 

######################################## 

## parent.py ## 
#!/usr/bin/python 
from subprocess import Popen, PIPE 

# cmd = [ 'capitalize.sh' ] # This would work 
cmd = [ 'script', '-q', '-f', '-c', 'capitalize.sh', '/dev/null'] 

p = Popen(cmd, stdin=PIPE) 
p.stdin.write("some string\n") 
p.wait() 

當通過script跑,我得換行的穩定印刷(如果這是一個Python,子進程,它會引發EOFerror)。

回答

1

一種替代方法是

p = subprocess.Popen(["python", "-u", "sub.py"], stdout=subprocess.PIPE) 

或建議here

我的經驗是,是的,你將能夠從大多數C程序中讀取而無需額外的努力。

Python解釋器需要額外的步驟來緩衝其輸出,這就是爲什麼它需要-u開關來禁用輸出緩衝。你的典型C程序不會這樣做。

我沒有遇到任何程序(C或其他),而不是Python解釋器,我預計工作,並沒有在一個子shell。

+1

我以前處理了這個問題。並非所有的C程序都可以使用。有一個稱爲腳本的令人敬畏的unix命令,可以讓你的工作儘管如此。看到我的問題類似地使用它:http://stackoverflow.com/questions/11131825/main-python-process-is-stopped-using-subprocess-calls-in-socketserver – korylprince

+0

它不與我的'c_prog'一起工作。如果我將它的標準輸出到一個文件,然後鍵盤中斷,文件將是空的。但是,如果我讓它自然終止,輸出使它到文件..我懷疑這是相關的。 – ajwood

+0

@korylprince:當我通過'script'使用PIPE運行std和stdout子進程時,子進程似乎失敗並帶有EOFError。 – ajwood

0

無論「-u」是什麼,shell都可以立即讀取輸出的原因是因爲您從shell啓動的程序將其輸出連接到TTY。當stdout連接到TTY時,它是無緩衝的(因爲它由TTY緩衝)。當你從python啓動python子進程時,你將stdout連接到一個管道,這意味着當它感覺像是它在子進程的衝突輸出它的輸出。

如果你正在尋找做一個子進程複雜的相互作用,考慮this tutorial.