拦截正在运行的subprocess的stdout

如果这是我的subprocess:

import time, sys for i in range(200): sys.stdout.write( 'reading %i\n'%i ) time.sleep(.02) 

这是控制和修改子stream程输出的脚本:

 import subprocess, time, sys print 'starting' proc = subprocess.Popen( 'c:/test_apps/testcr.py', shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE ) print 'process created' while True: #next_line = proc.communicate()[0] next_line = proc.stdout.readline() if next_line == '' and proc.poll() != None: break sys.stdout.write(next_line) sys.stdout.flush() print 'done' 

为什么readlinecommunicate等待进程完成运行? 有一个简单的方法来实时传递(和修改)subprocess的标准输出吗?

顺便说一句,我已经看到了这一点 ,但我不需要日志loggingfunction(并没有打扰了很多)。

我在Windows XP上。

正如Charles已经提到的那样,问题在于缓冲。 在为SNMPd编写一些模块时遇到了类似的问题,并通过用自动刷新版本replacestdout来解决这个问题。

我使用了以下代码,受到ActiveState上一些post的启发:

 class FlushFile(object): """Write-only flushing wrapper for file-type objects.""" def __init__(self, f): self.f = f def write(self, x): self.f.write(x) self.f.flush() # Replace stdout with an automatically flushing version sys.stdout = FlushFile(sys.__stdout__) 

过程输出被缓冲。 在更多的UNIX操作系统(或者Cygwin)上, pexpect模块是可用的,其中列举了所有必要的咒语以避免与缓冲相关的问题。 然而,这些咒语需要一个工作的pty模块 ,这在Python的本地(非cygwin)win32版本上是不可用的。

在你控制subprocess的例子中,你可以在需要时调用sys.stdout.flush() ,但是对于任意的subprocess,这个选项是不可用的。

另请参阅“为什么不使用pipe道(popen())”问题? 在pexpect常见问题。