38

因此,我注意到subprocess.call在继续执行 python 脚本之前等待命令完成时,我无法获取标准输出,除了subprocess.Popen. 是否有任何替代函数调用会等到它完成?(我也试过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使用它。

4

5 回答 5

86

我正在使用以下构造,尽管您可能希望避免使用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
于 2012-11-15T13:22:20.403 回答
21
subprocess.check_output(...)

调用该进程,如果其错误代码非零则引发,否则返回其标准输出。这只是一个快速的速记,所以你不必担心PIPEs 和其他事情。

于 2012-11-15T13:31:25.683 回答
17

如果您的进程提供了巨大的标准输出而没有标准错误,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()从中和
  • 你可以迭代它。

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

于 2012-11-15T13:24:50.667 回答
2

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

import subprocess
import sys
res = subprocess.run(
        [
          sys.executable, # venv3.8/bin/python
          'main.py', 
          '--help',
        ], 
        stdout=subprocess.PIPE, 
        text=True
)
print(res.stdout)
于 2020-04-13T16:13:31.953 回答
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 语法解析器,你最终会做大量的管道工作。

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

于 2013-04-10T05:27:34.553 回答