如何使用Python运行子进程,等待它退出并将完整的stdout作为字符串?

时间:2012-11-15 13:17:52

标签: python subprocess

所以我注意到subprocess.call在继续使用python脚本之前等待命令完成,除了使用subprocess.Popen之外我无法获取stdout。有任何替代函数调用会等到它完成吗? (我也试过Popen.wait

注意:我正在尝试避免os.system来电

result = subprocess.Popen([commands...,
                        self.tmpfile.path()], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = result.communicate()
print out+"HIHIHI"

我的输出:

HIHIHI

注意:我正在尝试使用此功能运行wine

5 个答案:

答案 0 :(得分:65)

我正在使用以下构造,尽管您可能希望避免使用shell=True。这为您提供了任何命令的输出和错误消息,以及错误代码:

process = subprocess.Popen(cmd, shell=True,
                           stdout=subprocess.PIPE, 
                           stderr=subprocess.PIPE)

# wait for the process to terminate
out, err = process.communicate()
errcode = process.returncode

答案 1 :(得分:19)

subprocess.check_output(...)

调用进程,如果其错误代码非零,则引发进程,否则返回其stdout。这只是一个快速的简写,所以你不必担心PIPE和事情。

答案 2 :(得分:13)

如果你的进程提供了一个巨大的stdout且没有stderr,由于内存限制,communicate()可能是错误的方法。

相反,

process = subprocess.Popen(cmd, shell=True,
                           stdout=subprocess.PIPE, 
                           stderr=subprocess.PIPE)

# wait for the process to terminate
for line in process.stdout: do_something(line)
errcode = process.returncode

可能是要走的路。

process.stdout是一个类似文件的对象,您可以将其视为任何其他此类对象,主要是:

  • 你可以read()从它
  • 你可以readline()从它和
  • 你可以迭代它。

后者就是我上面所做的,以便逐行获取其内容。

答案 3 :(得分:1)

我会尝试类似的事情:

#!/usr/bin/python
from __future__ import print_function

import shlex
from subprocess import Popen, PIPE

def shlep(cmd):
    '''shlex split and popen
    '''
    parsed_cmd = shlex.split(cmd)
    ## if parsed_cmd[0] not in approved_commands:
    ##    raise ValueError, "Bad User!  No output for you!"
    proc = Popen(parsed_command, stdout=PIPE, stderr=PIPE)
    out, err = proc.communicate()
    return (proc.returncode, out, err)

...换句话说,让shlex.split()完成大部分工作。我不会尝试解析shell的命令行,查找管道运算符并设置自己的管道。如果你要这样做那么你基本上必须编写一个完整的shell语法解析器,你最终会做很多的管道。

当然这引出了一个问题,为什么不将 Popen shell = True (关键字)选项一起使用?这将允许您将一个字符串(不拆分或解析)传递给shell,并仍然收集结果以按您的意愿处理。我的示例不会处理可能在命令中的任何管道,反引号,文件描述符重定向等,它们都将作为命令的文字参数出现。因此,使用 shell = True 运行更安全...我给出了一个愚蠢的例子,检查命令对某种“已批准的命令”字典或集合 - 通过它会使更有意义的是将其规范化为绝对路径,除非您打算在将命令字符串传递给此函数之前要求对参数进行规范化。

答案 4 :(得分:1)

对于Python 3.8,这对我有用。例如在venv中执行python脚本:

    import subprocess
    import sys
    res = subprocess.run([
              sys.executable,            # venv3.8/bin/python
              'main.py', '--help',], 
            stdout=PIPE, 
            text=True)
    print(res.stdout)