我有一个脚本parent.py
试图从Python中的子进程sub.py
读取stdout。
父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
来打印“hello world!”中的'h'。实际上,它挂了。我只能通过将-u
添加到sub.py
的she-bang行来获得我预期的行为。
这让我感到困惑,因为当-u
直接从shell运行时,sub.py
开关没有任何区别;与parent.py
不同,shell在某种程度上与未刷新的输出流有关。
我的目标是运行一个C程序作为子进程,所以我无法控制它是否刷新stdout。如果从subprocess.Popen
运行相同的东西,shell对进程的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)。
答案 0 :(得分:1)
另一种选择是
p = subprocess.Popen(["python", "-u", "sub.py"], stdout=subprocess.PIPE)
或建议here。
我的经验是,是的,您将能够从大多数C程序中读取而无需任何额外的努力。
Python解释器采取额外的步骤来缓冲其输出,这就是为什么它需要-u
开关来禁用输出缓冲。你典型的C程序不会这样做。
除了我希望工作的Python解释器之外,我没有遇到任何程序(C或其他),并且不在子shell中。
答案 1 :(得分:0)
无论“-u”如何,shell都可以立即读取输出的原因是因为从shell启动的程序将其输出连接到TTY。当stdout连接到TTY时,它是无缓冲的(因为它取决于要缓冲的TTY)。当您从python中启动python子进程时,您将stdout连接到管道,这意味着您可以在子进程的情况下在其感觉时刷新其输出。
如果您希望与子流程进行复杂的交互,请查看this tutorial.