我正在尝试为一个命令行程序(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*)?
发布于 2019-09-17 16:49:39
在Python3.x中,该进程可能会挂起,因为输出是字节数组而不是字符串。确保将其解码为字符串。
从Python3.6开始,您可以使用Popen Constructor中的参数encoding来完成此操作。完整的示例:
process = subprocess.Popen(
'my_command',
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
shell=True,
encoding='utf-8',
errors='replace'
)
while True:
realtime_output = process.stdout.readline()
if realtime_output == '' and process.poll() is not None:
break
if realtime_output:
print(realtime_output.strip(), flush=True)注意,这段代码redirects stderr to stdout redirects handles output errors。
https://stackoverflow.com/questions/803265
复制相似问题