2009-02-09 74 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常見問題。

相關問題