如何使用子进程 Popen.communicate() 方法?

Posted

技术标签:

【中文标题】如何使用子进程 Popen.communicate() 方法?【英文标题】:How to use the subprocess Popen.communicate() method? 【发布时间】:2017-05-24 10:01:11 【问题描述】:

我正在尝试将 bash 命令的标准输出作为 Python 中的字符串。按照Popen 文档,我试过了:

import subprocess

p = subprocess.Popen(["echo", "hello"])
stdoutdata, stderrdata = p.communicate()

print stdoutdata

运行此脚本会产生以下输出:

hello
None
[Finished in 0.0s]

因此,尽管 Python 正在打印输出,但 stdoutdata 变量是 None,而不是我想要的 "hello"。我怎样才能做到这一点?

【问题讨论】:

【参考方案1】:

您没有向 Popen 构造函数提供任何标准输出,默认功能只是将输出写入父级的标准输出句柄。因此,您会看到它被打印在您的外壳中。

引用Popen's docs:

使用默认设置None,不会发生重定向;子文件句柄将从父文件继承。


要在结果元组中填充标准输出,请使用 subprocess.PIPE 作为标准输出。

引用docs:

要在结果元组中获得除 None 以外的任何内容,您需要给出 stdout=PIPE 和/或 stderr=PIPE 也是。

>>> import subprocess
>>> p = subprocess.Popen(["echo", "hello"], stdout=subprocess.PIPE)
>>> p.communicate()
('hello\n', None)

【讨论】:

【参考方案2】:

您需要将stdoutstderr 标志传递给Popen 构造函数。 默认情况下,它们被设置为None,导致Popen 没有捕获它们。

cmd = subprocess.Popen(["echo", "hello"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = cmd.communicate()
# retCode = cmd.returncode
# retCode != 0, indicates an error occured in execution.
print (out)
>>> b'hello\n'

【讨论】:

【参考方案3】:

看来subprocess.check_output 方法是我需要的:

import subprocess
output = subprocess.check_output(["echo", "hello"])

正如我所料,output 现在是 'hello\n'(包括换行符)。

【讨论】:

以上是关于如何使用子进程 Popen.communicate() 方法?的主要内容,如果未能解决你的问题,请参考以下文章

Unix Popen.communicate无法gzip大文件

python子进程模块subprocess详解

python popen.communicate() 与多个标准输入写入

了解 Popen.communicate

带有标准输入的 subprocess.Popen.communicate() 的管道损坏

[python subprocess学习篇] 调用系统命令