我的python脚本使用subprocess来调用非常嘈杂的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代码进行排序 .
我错过了什么?这甚至可能吗?
Update:
如果将 sys.stdout.flush()
添加到fake_utility.py,则代码在python 3.1中具有所需的行为 . 我正在使用python 2.6 . 您会认为使用 proc.stdout.xreadlines()
与py3k的工作方式相同,但事实并非如此 .
Update 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()
6 回答
自从我上次使用Python以来已经很长时间了,但我认为问题在于
for line in proc.stdout
语句,它在迭代之前读取整个输入 . 解决方案是使用readline()
代替:当然,你仍然需要处理子进程的缓冲 .
注意:带有迭代器的解决方案应该等效于使用
readline()
,除了预读缓冲区,但是(或者正是因为这个)建议的更改确实为我产生了不同的结果(Windows XP上的Python 2.5) .派对迟到了,但很惊讶没有看到我认为这里最简单的解决方案:
实际上,如果您整理了迭代器,那么缓冲现在可能是您的问题 . 您可以告诉子进程中的python不要缓冲其输出 .
变
从python中调用python时我需要这个 .
您想将这些额外参数传递给
subprocess.Popen
:然后你可以像你的例子一样迭代 . (使用Python 3.5测试)
以下对Rômulo的回答的修改对Python 2和3(2.7.12和3.6.1)起作用:
我用python3尝试了这个并且它有效,source