从子流程实时打印输出 [英] Printing output in realtime from subprocess
问题描述
我正在尝试为子进程实时打印stdout,但即使在bufsize = 0的情况下,stdout也似乎已被缓冲,我不知道如何使其工作,我总是有一个延迟.
I'm trying to print stdout in realtime for a subprocess but it looks like stdout is buffered even with bufsize=0 and I can't figure out how to make it work, I always have a delay.
我尝试的代码:
p = subprocess.Popen(cmd,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
bufsize=0)
line = p.stdout.readline()
while line:
sys.stdout.write(line)
sys.stdout.flush()
# DO OTHER STUFF
line = p.stdout.readline()
也尝试使用for line in iter(p.stdout.readline, b'')
代替while循环,并尝试使用read(1)
代替readline()
.总是相同的结果,输出会延迟很多秒或几分钟,并且突然出现多行.
Also tried with for line in iter(p.stdout.readline, b'')
instead of the while loop and with read(1)
instead of readline()
. Always the same result, the output gets delayed by a lot of seconds or minutes and multiple lines appear suddenly at once.
我认为会发生的事情:
bufsize
设置为0(根据docs,默认情况下设置为0),因此通过管道传到p.stdout
的行应立即可用.但是,由于p.stdout.readline()
在传送新行时不会立即返回,这意味着它已被缓冲,因此,当缓冲区最终刷新到p.stdout
时,会同时显示多行.
bufsize
is set to 0 ( it is set to 0 by default according to the docs ) so the lines piped top.stdout
should be available immediately. But since p.stdout.readline()
doesn't return immediately when a new line is piped, that means that it IS buffered, hence the multiple lines at once when the buffer is finally flushed to p.stdout
.
我该怎么做才能使其正常工作?
What can I do to make it work ?
推荐答案
感谢pobrelkey谁找到了问题的根源.的确,延迟是由于以下事实造成的:子进程正在缓冲对stdout的写操作,因为它没有在写tty.子级使用stdio
,该值在写入tty时将被行缓冲,否则将被完全缓冲.
Thanks to pobrelkey who found the source of the problem. Indeed, the delay is due to the fact that the child is buffering its write to stdout because it is not writing to a tty. The child uses stdio
which is line buffered when writing to a tty, else it is fully buffered.
我设法通过使用pexpect
而不是subprocess
使它正常工作. pexpect
使用伪tty,这正是我们在这里所需要的:
I managed to get it to work by using pexpect
instead of subprocess
. pexpect
uses a pseudo-tty and that's exactly what we need here :
p = pexpect.spawn(cmd,args,timeout=None)
line = p.readline()
while line:
sys.stdout.write(line)
sys.stdout.flush()
# DO OTHER STUFF
line = p.readline()
就我而言甚至更好:
p = pexpect.spawn(cmd,args,timeout=None,logfile=sys.stdout)
line = p.readline()
while line:
# DO OTHER STUFF
line = p.readline()
没有更多的延迟!
有关pexpect的更多信息: wiki
More infos about pexpect : wiki
这篇关于从子流程实时打印输出的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!