2012-09-28 149 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.