我正在尝试为一个命令行程序(svnadmin I)编写一个包装器脚本,它将显示一个很好的操作进度指示器。这要求我能够在包装的程序输出后立即看到它的每一行输出。
我想我只需要使用subprocess.Popen
执行程序,使用stdout=PIPE
,然后读取传入的每一行,并对其执行相应的操作。然而,当我运行下面的代码时,输出似乎被缓冲在某处,导致它出现在两个块中,第1到332行,然后是333到439 (输出的最后一行)。
from subprocess import Popen, PIPE, STDOUT
p = Popen('svnadmin verify /var/svn/repos/config', stdout = PIPE,
stderr = STDOUT, shell = True)
for line in p.stdout:
print line.replace('\n', '')
在看了一些关于子进程的文档之后,我发现了Popen
的bufsize
参数,所以我尝试将bufsize设置为1(每行缓冲)和0(无缓冲),但这两个值似乎都没有改变行的传递方式。
在这一点上,我开始抓取吸管,所以我编写了以下输出循环:
while True:
try:
print p.stdout.next().replace('\n', '')
except StopIteration:
break
但得到的结果是一样的。
是否有可能获得使用子进程执行的程序的“实时”程序输出?在Python语言中有没有其他向前兼容的选项(不是exec*
)?
发布于 2009-04-29 17:26:54
我试过了,出于某种原因,当代码
for line in p.stdout:
...
积极地缓冲,变种
while True:
line = p.stdout.readline()
if not line: break
...
不会。显然这是一个已知的bug:http://bugs.python.org/issue3907 (这个问题现在已经在2018年8月29日“关闭”了)
发布于 2011-06-21 00:13:51
通过将缓冲区大小设置为1,您实际上强制该进程不缓冲输出。
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, bufsize=1)
for line in iter(p.stdout.readline, b''):
print line,
p.stdout.close()
p.wait()
发布于 2018-02-21 16:17:06
您可以将子流程输出直接定向到流中。简化示例:
subprocess.run(['ls'], stderr=sys.stderr, stdout=sys.stdout)
https://stackoverflow.com/questions/803265
复制相似问题