2012-04-28 92 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