2009-02-09 37 views
21

,而如果这是我的子流程:拦截子进程的标准输出它运行

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

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

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等到过程完成后再运行?有没有简单的方法来实时传递(和修改)子进程的stdout?

顺便说一句,我见过this,但我不需要日志记录功能(并且不需要太多理解)。

我在Windows XP上。

+0

相关:[?如何冲洗的Python打印的输出(http://stackoverflow.com/q/230751/95735) – 2012-10-30 20:31:42

回答

14

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

我用下面的代码,对ActiveState的启发一些柱:

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__) 
+0

我没有看到这与每个sys.stdout.readline()之后调用sys.stdout.flush()是什么不同,这正是我所做的。我也尝试为子进程设置bufsize = 0。 – Paul 2009-02-09 12:12:34

7

过程输出被缓冲。在更多的UNIXy操作系统(或Cygwin)上,可以使用pexpect模块,该模块介绍了避免缓冲相关问题的所有必要咒语。但是,这些咒语需要工作pty module,这在Python的本地(非cygwin)win32版本上不可用。

在您控制子流程的示例中,您可以在需要时调用sys.stdout.flush() - 但对于任意子流程,该选项不可用。

另请参阅the question "Why not just use a pipe (popen())?"在pexpect常见问题。

相关问题