2012-04-28 112 views
7

我正在試圖與使用python subprocess.Popen()調用的子進程交談。在我真正的代碼中,我正在實現一種IPC,所以我想寫一些數據,讀取響應,寫入更多數據,讀取響應等等。正因爲如此,我不能使用Popen.communicate(),否則它適用於簡單的情況。閱讀/寫入Popen()子進程

此代碼顯示我的問題。它甚至從來沒有得到第一個反應,掛在第一個「閱讀結果」。爲什麼?我如何能夠按照我的預期進行這項工作?

import subprocess 
p = subprocess.Popen(["sed", 's/a/x/g'], 
        stdout = subprocess.PIPE, 
        stdin = subprocess.PIPE) 

p.stdin.write("abc\n") 
print "Reading result:" 
print p.stdout.readline() 

p.stdin.write("cat\n") 
print "Reading result:" 
print p.stdout.readline() 

回答

4

我會嘗試,如果你能爲它做了很多對你的好東西使用Popen().communicate(),但如果你需要使用Popen()像你描述的完全相同,您將需要設置SED用換行後刷新其緩衝區該-l選項:

p = subprocess.Popen(['sed', '-l', 's/a/x/g'], 
        stdout=subprocess.PIPE, 
        stdin=subprocess.PIPE) 

,你的代碼應該可以正常

+1

的確如此!由於某種原因,我的sed使用-u作爲「無緩衝」,而不是-l,但它的工作原理完全相同。這解決了我的示例代碼,但不幸的是不是我真正的代碼,因爲實際的命令不是sed,而是另一個python程序。雖然你的回答很好,但你指出了這個問題。 – 2012-04-28 15:39:23

+1

是的,問題解決了。問題是輸出緩衝結果。在我的子進程中做一個簡單的stdout.flush()解決了這個問題。謝謝! – 2012-04-28 15:51:15

3

sed的輸出進行緩衝,並只直到足夠已經累積或輸入流用盡或關閉輸出其數據。

試試這個:

import subprocess 
p = subprocess.Popen(["sed", 's/a/x/g'], 
        stdout = subprocess.PIPE, 
        stdin = subprocess.PIPE) 

p.stdin.write("abc\n") 
p.stdin.write("cat\n") 
p.stdin.close() 

print "Reading result 1:" 
print p.stdout.readline() 

print "Reading result 2:" 
print p.stdout.readline() 

請注意,這不能可靠一旦緩衝區已滿完成其龐大的數據wriring到stdin塊。最好的方法是使用communicate()

+0

但sed的在外殼直接運行命令時不採取行動的方式。如果你這樣做,那麼響應會在每一行之後出現。即使我在編寫完成後調用p.stdin.flush(),問題仍然存在。另外,在現實生活中,我也編寫了被調用的程序,沒有緩衝,它的行爲方式相同。我不相信緩衝是這裏的問題。 – 2012-04-28 15:19:40

+2

啊,你說得對,緩衝確實是問題所在。 – 2012-04-28 15:53:12