【问题标题】:Output of subprocess both to PIPE and directly to stdout子进程的输出到 PIPE 和直接到标准输出
【发布时间】:2015-06-15 23:23:05
【问题描述】:

我发现了一些看起来像我的问题,但没有产生我可以使用的解决方案(最接近的是:subprocess output to stdout and to PIPE

问题:我想使用子进程启动一个需要很长时间的进程。运行命令后,我需要解析 stdout-output 和 stderr-output。

目前我的做法如下:

p = subprocess.Popen( command_list, stdout=subprocess.PIPE, 
    stderr=subprocess.PIPE )
out, error_msg = p.communicate()
print out + "\n\n" + error_msg

#next comes code in which I check out and error_msg

但是这种方法的缺点是用户在运行时看不到进程的输出。仅在最后打印输出。

有没有一种方法可以在命令运行时打印输出(就像我在没有 stdout/stderr=subprocess.PIPE 的情况下给出的命令一样)并且最后仍然通过 p.communicate 输出?

注意:我目前正在 python 2.5(使用此 python 版本的旧软件版本)上进行开发。

【问题讨论】:

标签: python subprocess


【解决方案1】:

这个sn-p曾经帮助过我一次类似的情况:

process = subprocess.Popen(cmd, bufsize=1, universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in iter(process.stdout.readline, ''):
    print line,
    sys.stdout.flush() # please see comments regarding the necessity of this line 
process.wait()
errcode = process.returncode

【讨论】:

  • 如果您确实需要瞬时输出,flush() 可能很有用,但如果您只关心从生成足够输出以缓冲无关紧要的进程中看到一些进展,则不是绝对必要的很多。如果它是一个非常慢的写入器,当然,缓冲区填满需要很长时间;然后也许你确实想经常flush()
  • @tripleee:如果我们假设python 进程和子进程具有相同的缓冲策略(如果它们都基于stdio),我发现这里不需要sys.stdout.flush(),即如果@ 987654326@ 脚本在终端中运行(无重定向),然后标准输出已经是行缓冲的——不需要sys.stdout.flush()。如果输出被重定向到文件(尽管 OP 要求),那么flush() 会不必要地减慢打印速度(通常在输出文件时使用的块缓冲更有效,每行之后的刷新会使其变慢)。
  • 如果给出了--line-buffering 选项(如grep),我会明确调用flush()
  • 注意:stderr=STDOUT 在此处合并 stdout/stderr。 OP 可能想单独捕获它们。
  • @Nemelis:不幸的是,单独捕获 stdout/stderr 会使代码复杂很多:您需要线程或 select() 或其他异步 I/O 工具。请参阅我上面链接的问题。
最近更新 更多