首页 > 解决方案 > 将 STDOUT 提供给 stdout 会为 subprocess.run 返回 errno9

问题描述

我想允许我的程序的用户指定输出是否应该是详细的。即,运行子进程正在打印它们生成或不生成的所有输出。

我曾经能够做到:

out = subprocess.DEVNULL
if verbose:
   out = subprocess.STDOUT
subprocess.run(['ls','-la'],stderr=out,stdout=out)

但这会导致此错误:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.8/subprocess.py", line 489, in run
    with Popen(*popenargs, **kwargs) as process:
  File "/usr/lib/python3.8/subprocess.py", line 854, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,
  File "/usr/lib/python3.8/subprocess.py", line 1702, in _execute_child
    raise child_exception_type(errno_num, err_msg, err_filename)
OSError: [Errno 9] Bad file descriptor

我能够将错误缩小到:

subprocess.run(['ls','-la'],stdout=out)

即,定义输出应该去标准输出会导致这个问题。在早期(即,< 3.8)的 Python 中,情况并非如此。

这是设计使然吗?如何在不加倍 subprocess.run 调用的情况下仍然实现详细/非详细区别?

标签: python-3.xsubprocess

解决方案


您可以使用以下capture_output选项:

如果 capture_output 为真,stdout 和 stderr 将被捕获。使用时,内部 Popen 对象会自动创建为 stdout=PIPE 和 stderr=PIPE。stdout 和 stderr 参数可能不会与 capture_output 同时提供。如果您希望捕获两个流并将其合并为一个,请使用 stdout=PIPE 和 stderr=STDOUT 而不是 capture_output。

subprocess.run(['ls','-la'], capture_output=not verbose)

stdout 参数采用 None、subprocess.PIPE、文件对象或文件描述符,但不是subprocess.STD_OUT一个特殊值,表示 stderr 应该转到 stdout。

如果您希望子进程不打印任何内容并在内存中不保留任何内容,您也可以传递subprocess.DEVNULLtostdoutsubprocess.STDOUTto 。stderr

subprocess.run(
    ["ls", "-la"], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT
)

对于详细模式,默认值(两个参数都为 None)可以。您还可以传递sys.stdouttostdoutsys.stderrto stderr。所有这些都是等效的:

subprocess.run(
    ["ls", "-la"]
)
subprocess.run(
    ["ls", "-la"], stdout=None, stderr=None
)
subprocess.run(
    ["ls", "-la"], stdout=sys.stdout, stderr=sys.stderr
)

推荐阅读