【问题标题】:Redirect subprocess stdout to stderr将子进程标准输出重定向到标准错误
【发布时间】:2022-12-14 03:17:49
【问题描述】:

Python 的 subprocess API 的一个标准功能是使用关键字参数组合 STDERR 和 STDOUT

stderr = subprocess.STDOUT

但目前我需要相反的方法:将命令的 STDOUT 重定向到 STDERR。现在我正在使用subprocess.getoutputsubprocess.check_output 手动执行此操作并打印结果,但是是否有更简洁的选项?

【问题讨论】:

  • 只是好奇,你为什么要那样做管道?对我来说,如果你像你提到的那样将 STDERR 传递给 STDOUT ,结果似乎是完全一样的。
  • @Tzane 如果它在终端中运行,结果将是相同的,但如果它是管道的一部分,或者如果它来自 cron 之类的东西,则结果将不同。例如,如果您有一个程序运行您的脚本并忽略 stdout,但如果有任何内容写入 stderr,则会通过电子邮件发送给您,您可能希望将所有输​​出重定向到 stderr。

标签: python subprocess io-redirection


【解决方案1】:

衔尾蛇在彗星中提到我们应该能够做类似的事情

subprocess.run(args, stdout = subprocess.STDERR)

但是,文档没有提到 subprocess.STDERR 的存在,至少在我的安装 (3.8.10) 中实际上并不存在。

根据文档,

stdin、stdout 和 stderr 分别指定执行程序的标准输入、标准输出和标准错误文件句柄。有效值为 PIPE、DEVNULL、现有文件描述符(正整数)、具有有效文件描述符的现有文件对象和 None。

假设你在一个 UNIX 类型的系统上(如果你不是,我不确定你打算用 stdout / stderr 做什么),stdin/stdout/stderr 的文件描述符总是相同的:

  • 0 是标准输入
  • 1 是标准输出
  • 2 是标准错误
  • 3+ 用于您在程序中创建的 fds

所以我们可以做类似的事情

subprocess.run(args, stdout = 2)

运行进程并将其 stdout 重定向到 stderr。

当然,我建议您将其保存为某个地方的常量,而不是只在那里留下一个原始数字 2。如果您使用的是 Windows 或其他系统,您可能需要做一些研究,看看它们是否完全相同。

更新:

随后的搜索表明此编号约定为part of POSIX,而Windows explicitly obeys it

更新:

@kdb 在 cmets 中指出 sys.stderr 通常会满足“具有有效文件描述符的现有文件对象”条件,使其成为此处使用原始 fd 的有吸引力的替代方案。

【讨论】:

  • 在 Windows subprocess.STDOUT = -2 上,所以这可能只是 UNIX 特定的,就像你说的那样。
  • 是的,我在发表评论后意识到 STDERR 不存在于 subprocess 中。还有 STD_ERROR_HANDLESTD_INPUT_HANDLESTD_OUTPUT_HANDLE,但我不确定它们是否适用于这种情况。
  • @Tzane 看起来 subprocess.STDOUT 在 Linux 上也是 -2。我不认为那是一个实际的 fd,它只是子进程选择的一些值,它不能是一个实际的 fd,它可以用来确保完整的跨平台支持,无论平台有多奇怪。
  • 实际上,您间接提到了解决方案,结果证明这是一个值得“我应该更好地阅读文档”的案例:有效值为 [...]现有文件对象使用有效的文件描述符,[...].这意味着以下通常有效:subprocess.check_call(['ls', '-l'], stdout=sys.stderr)。尽管在模块覆盖sys.stderr 的情况下它可能会失败,因此它可能不像subprocess.STDOUT 那样通用。
猜你喜欢
  • 2012-05-26
  • 1970-01-01
  • 2012-08-15
  • 1970-01-01
  • 2020-11-05
  • 2013-06-02
  • 2013-07-16
  • 1970-01-01
  • 2011-05-16
相关资源
最近更新 更多