Python - 同时捕获Popen的stdout并在控制台显示?

5 投票
5 回答
11705 浏览
提问于 2025-04-15 13:37

我想要从一个运行时间比较长的程序中获取输出,这个程序是通过 subprocess.Popen(...) 启动的,所以我使用了 stdout=PIPE 这个参数。

不过,因为这个程序运行时间比较长,我还想把输出显示到控制台上(就像我没有使用管道一样),这样可以让使用这个脚本的人知道程序还在继续工作。

这样做有可能吗?

谢谢。

5 个回答

2

S. Lott的评论提到了使用子进程获取实时输出在Python中实时拦截另一个进程的标准输出这两个链接。

我很好奇,Alex在这里的回答和他在问题1085071中的回答为什么不一样。我对这两个问题中提到的答案做了一些简单的小实验,结果都不错……

我根据Alex上面的回答去看了wexpect,但我必须说,看完代码里的评论后,我对使用它的感觉并不好。

我想这里的一个大问题是,什么时候pexpect/wexpect会成为内置的工具库之一呢?

5

你长时间运行的子进程可能会导致输出到控制台的内容不流畅,体验很糟糕。我建议你考虑使用pexpect(在Windows上可以用wexpect)来解决这个缓冲问题,这样可以让子进程的输出更加平滑和规律。例如(在几乎所有类Unix系统上,安装好pexpect后):

>>> import pexpect
>>> child = pexpect.spawn('/bin/bash -c "echo ba; sleep 1; echo bu"', logfile=sys.stdout); x=child.expect(pexpect.EOF); child.close()
ba
bu
>>> child.before
'ba\r\nbu\r\n'

ba和bu之间的输出会有合适的时间间隔(大约一秒)。注意,这里的输出没有经过正常的终端处理,所以回车符会保留在里面——如果你需要用\n作为行结束符,你需要自己处理这个字符串(只需简单地用.replace替换一下就可以了!)。不经过处理是很重要的,特别是当子进程向标准输出写入二进制数据时,这样可以确保所有数据都保持完整!

1

你能不能直接把它从管道里读出来,然后用print打印出来呢?

撰写回答