如何抑制或捕获 subprocess.run() 的输出?

Posted

技术标签:

【中文标题】如何抑制或捕获 subprocess.run() 的输出?【英文标题】:How to suppress or capture the output of subprocess.run()? 【发布时间】:2017-05-01 12:09:02 【问题描述】:

subprocess.run() 上的文档中的示例看来,似乎不应该有任何输出

subprocess.run(["ls", "-l"])  # doesn't capture output

但是,当我在 python shell 中尝试它时,列表会被打印出来。我想知道这是否是默认行为以及如何抑制run() 的输出。

【问题讨论】:

***.com/questions/8529390/… subprocess.run() 默认情况下不捕获 stdout 或 stderr,为此需要为 stdout 和/或 stderr 参数传递 PIPEs(它在链接文档中) .因此,除非您这样做,否则它们将像通常从其他进程中一样显示。 你想抑制输出还是捕获它? 这个问题已被标记为重复,但我认为这是一个错误,因为 API 在 Python 2.7 (process.call) 和 Python 3.5 (process.run) 之间发生了显着变化。我来到这里明确地寻找这个问题的 Python 3 答案。这个问题的公认答案以及对此问题的最高评论在这种情况下都比其他问题的答案更有用。 由于Python 3.7你也可以只使用capture_output=True参数。 【参考方案1】:

这里是如何抑制输出,按清洁度递减的顺序。他们假设您使用的是 Python 3。

    您可以重定向到特殊的subprocess.DEVNULL 目标。
import subprocess

subprocess.run(['ls', '-l'], stdout=subprocess.DEVNULL)
# The above only redirects stdout...
# this will also redirect stderr to /dev/null as well
subprocess.run(['ls', '-l'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
# Alternatively, you can merge stderr and stdout streams and redirect
# the one stream to /dev/null
subprocess.run(['ls', '-l'], stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
    如果你想要一个完全手动的方法,可以通过自己打开文件句柄重定向到/dev/null。其他一切都与方法 #1 相同。
import os
import subprocess

with open(os.devnull, 'w') as devnull:
    subprocess.run(['ls', '-l'], stdout=devnull)

这里是如何捕获输出(以供以后使用或解析),按照清洁度递减的顺序。他们假设您使用的是 Python 3。以下示例使用 text=True(仅限 Python >= 3.7,在 Python universal_newlines=True,这与 Python 相同,但输入更冗长)将输出返回为 @987654328 @ 而不是 bytes - 省略 text=True/universal_newlines=True 以获取 bytes 数据。

    如果您只想独立捕获 STDOUT 和 STDERR,并且您使用的是 Python >= 3.7,请使用 capture_output=True
import subprocess

result = subprocess.run(['ls', '-l'], capture_output=True, text=True)
print(result.stdout)
print(result.stderr)
    您可以使用subprocess.PIPE 独立捕获STDOUT 和STDERR。这适用于支持subprocess.run任何版本的 Python。
import subprocess

result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE, universal_newlines=True)
print(result.stdout)

# To also capture stderr...
result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
print(result.stdout)
print(result.stderr)

# To mix stdout and stderr into a single string
result = subprocess.run(['ls', '-l'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, universal_newlines=True)
print(result.stdout)

【讨论】:

请注意,来自 Python 版本。 3.3其实有一个subprocess.DEVNULL,所以stdout参数可以不用open直接赋值,只用stdout=subprocess.DEVNULL即可。 我在 Python 3.7 上收到 NameError: name 'devnull' is not defined @Sabrina 你定义devnull了吗? 是否可以在打印输出的同时捕获管道中的数据(以供以后使用或解析)? @Christopher 如果您不关心程序运行时的打印,您可以在事后打印result.stdout。如果要实时捕获和打印,就有点复杂了,因为不能使用subprocess.run,需要低级的subprocess.Popen。当我需要这样做时,我使用了 like this answer 的东西(从 Python 3 的答案调整语法)。【参考方案2】:

例如:捕获ls -a的输出

import subprocess
ls = subprocess.run(['ls', '-a'], capture_output=True, text=True).stdout.strip("\n")
print(ls)

【讨论】:

这适用于 python 3.7,但不适用于 python 3.6(我得到TypeError: __init__() got an unexpected keyword argument 'capture_output' 最后一部分有助于获得干净的变量输出。

以上是关于如何抑制或捕获 subprocess.run() 的输出?的主要内容,如果未能解决你的问题,请参考以下文章

如何从 subprocess.run() 运行 pip install 命令 [重复]

如何使用 Python 3.6 的 subprocess.run() 在 Linux OS 中执行 .run 文件 [重复]

如何在 Python 3 中使用 stdin 将字符串传递给 subprocess.run

如何使用subprocess.run()来运行Hive查询?

如何在 python 中使用 subprocess.run() 运行 step-cli

将 subprocess.run 输出重定向到 jupyter notebook 的