逐行读取subprocess stdout

问题:

我的python脚本使用子进程调用非常嘈杂的linux实用程序。我想将所有输出存储到日志文件中,并向用户显示一些输出。我以为以下可以工作,但是在应用程序产生了大量的输出之前,输出不会显示在我的应用程序中。

#fake_utility.py, just generates lots of output over time
import time
i = 0
while True:
   print hex(i)*512
   i += 1
   time.sleep(0.5)

#filters output
import subprocess
proc = subprocess.Popen(['python','fake_utility.py'],stdout=subprocess.PIPE)
for line in proc.stdout:
   #the real code does filtering here
   print "test:", line.rstrip()

我真正想要的行为是过滤器脚本打印从子处理接收到的每一行。类似于tee,但使用python代码。
我失踪了什么这甚至可能吗
 更新:
如果将sys.stdout.flush()添加到fake_utility.py中,则代码在python 3.1中具有所需的行为。我使用的是python 2.6。你会认为使用proc.stdout.xreadlines()可以和py3k一样工作,但是没有。
 更新2:
这是最小的工作代码。

#fake_utility.py, just generates lots of output over time
import sys, time
for i in range(10):
   print i
   sys.stdout.flush()
   time.sleep(0.5)

#display out put line by line
import subprocess
proc = subprocess.Popen(['python','fake_utility.py'],stdout=subprocess.PIPE)
#works in python 3.0+
#for line in proc.stdout:
for line in iter(proc.stdout.readline,''):
   print line.rstrip()

回答:

自从我上次使用Python以来已经很久了,但是我认为问题在于语句for line in proc.stdout,它会在迭代之前读取整个输入。解决方案是使用readline()

#filters output
import subprocess
proc = subprocess.Popen(['python','fake_utility.py'],stdout=subprocess.PIPE)
while True:
  line = proc.stdout.readline()
  if line != '':
    #the real code does filtering here
    print "test:", line.rstrip()
  else:
    break

当然你还需要处理子进程的缓冲。
注意:according to the documentation使用迭代器的解决方案应等同于使用readline(),除了预读缓冲区,但(或正是因为这一点),建议的更改对我来说产生不同的结果(Windows XP上的Python 2.5 )。

 
 
Code问答: http://codewenda.com/topics/python/
Stackoverflow: read subprocess stdout line by line

*转载请注明本文链接以及stackoverflow的英文链接

发表评论

电子邮件地址不会被公开。 必填项已用*标注

85 + = 91