【问题标题】:How to unify stdout and stderr, yet be able to distinguish between them?如何统一标准输出和标准错误,但又能区分它们?
【发布时间】:2020-01-29 23:19:00
【问题描述】:

我想生成一个进程运行的可读 HTML 报告。为此,我想同时跟踪 stdoutstderr,并将它们交错输出,但要区分 - 例如,日志将根据它们发出的顺序显示它们两者的组合,但使用 stdout黑色和stderr 红色粗体。

我可以很容易地看到一个让它们与众不同的解决方案:只需将每个重定向到subprocess.PIPE。当然,那么它们不能按顺序重新组合。按顺序统一它们也很容易:只需将stderr 重定向到subprocess.STDOUT。但是,它们将无法区分。

因此,将输出要么区分按顺序组合很简单,但两者都不是。

在 Python 中有什么方法可以做到这一点?

【问题讨论】:

  • 我会在生成输出时将 stdout 和 stderr 包装在不同的 <span> 类中
  • @NullUserException 当然,但是你如何让它们保持有序,又能区分?我可以将两者都重定向到subprocess.PIPE,在这种情况下它们将被区分但分开,或者我可以将stderr 重定向到stdout,在这种情况下它们将被统一但不区分。
  • 当您在 shell 上执行此操作时,您实际上会得到 perfect 顺序,就像您在 Python 中使用 stderr=subprocess.STDOUT 时所做的一样,但这不会“保持他们与众不同”。
  • ...无论如何,如果您想尝试获得尽可能好的东西 - 有一个单独的线程读取每个 FD 并在接收到它时处理其内容,程序执行写入配置为无缓冲或行缓冲模式(如何做到这一点是特定于工具的,尽管在 GNU 平台上有 stdbuf,如果程序坚持使用 glibc 提供的输出缓冲默认值,它将起作用)。
  • ...在 shell(或 Python 高级等效项)上运行 2>&1 会复制文件描述符,使 FD 2 指向与 FD 相同的内核空间对象 1,所以写入是有序的,但也无法区分。

标签: python subprocess stdout stderr


【解决方案1】:

您可以使用select() 来复用输出。假设您在管道中捕获了 stdout 和 stderr,则此代码将起作用:

import select
import sys

inputs = set([pipe_stdout, pipe_stderr])

while inputs:
  readable, _, _ = select.select(inputs, [], [])
  for x in readable:
    line = x.readline()
    if len(line) == 0:
      inputs.discard(x)
    if x == pipe_stdout
      print 'STDOUT', line
    if x == pipe_stderr
      print 'STDERR', line

【讨论】:

  • 这是真的,但它不保证未修改/原始排序。尝试使用一个程序,将单个写入交错到 stdout 和 stderr ——如果它足够快地完成这些写入,你将有团块 (stdout/stdout/stderr/stderr) 而不是保留交错的 @ 987654327@/stderr/stdout/stderr.
  • 不刷源程序,不修改源程序打标签,我觉得这样就可以了。
  • 我同意;我要说的是,应该明确区分(“尽善尽美”不是“完美”)。
  • @CharlesDuffy 我认为这是我们能做的最好的。使用 Mark 的解决方案,您将获得的任何缺乏秩序与您在 shell 级别将 stderr 重定向到 stdout 所获得的结果相同。所以这似乎是最好的解决方案。
  • @DunPeal, ...不,“同样你会在 shell 级别得到 [...]”不是真的;在 shell 级别将 stderr 重定向到 stdout 可以为您提供更强的保证(就像将 stdout=subprocess.STDERR 传递给 subprocess.Popen 一样),因为当您这样做时,两个 FD 引用相同的底层对象,所以 确实 在写入它们之间存在定义明确的序列化。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-25
  • 1970-01-01
相关资源
最近更新 更多