按lin读取子进程stdout行

2024-04-24 21:56:40 发布

您现在位置:Python中文网/ 问答频道 /正文

我的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()

我真正想要的行为是让筛选脚本在从子流程接收到每一行时打印它们。Sorta喜欢^{}除了使用python代码之外所做的事情。

我错过了什么?这可能吗?


更新:

如果将sys.stdout.flush()添加到fake_utility.py中,则代码在python 3.1中具有所需的行为。我正在使用Python2.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()

Tags: 代码inpyimportforoutputtimestdout
3条回答

派对有点晚了,但很惊讶没有看到我认为最简单的解决方案:

import io
import subprocess

proc = subprocess.Popen(["prog", "arg"], stdout=subprocess.PIPE)
for line in io.TextIOWrapper(proc.stdout, encoding="utf-8"):  # or another encoding
    # do something with line

(这需要Python 3。)

实际上,如果您整理了迭代器,那么缓冲现在可能是您的问题。您可以告诉子进程中的python不要缓冲其输出。

proc = subprocess.Popen(['python','fake_utility.py'],stdout=subprocess.PIPE)

变成

proc = subprocess.Popen(['python','-u', 'fake_utility.py'],stdout=subprocess.PIPE)

当从python内部调用python时,我需要这个。

我上次使用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 not line:
    break
  #the real code does filtering here
  print "test:", line.rstrip()

当然,您仍然需要处理子进程的缓冲。

注意:according to the documentation带迭代器的解决方案应该等同于使用readline(),除了预读缓冲区,但是(或者正是因为这个原因)提议的更改确实为我产生了不同的结果(Windows XP上的Python 2.5)。

相关问题 更多 >