从子流程实时打印输出 [英] Printing output in realtime from subprocess

查看:104
本文介绍了从子流程实时打印输出的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为子进程实时打印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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆