Python subprocess.call и subprocess.Popen stdout

Итак, я заметил subprocess.call, пока он ждет завершения команды перед продолжением работы с python script, у меня нет способа получить stdout, кроме 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 с этим.

Ответы

Ответ 1

Я использую следующую конструкцию, хотя вы можете избежать 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

Ответ 2

Если ваш процесс дает огромное значение 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

subprocess.check_output(...)

вызывает процесс, возникает, если его код ошибки отличен от нуля, и в противном случае возвращает его stdout. Это просто короткая стенография, поэтому вам не нужно беспокоиться о PIPE и вещах.

Ответ 4

Я бы попробовал что-то вроде:

#!/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() выполняет большую часть работы. Я бы НЕ попытался разобрать командную строку оболочки, найти операторов труб и настроить собственный конвейер. Если вы собираетесь это сделать, вам в основном придется написать полный синтаксический синтаксический анализатор синтаксиса, и вы в конечном итоге сделаете очень много сантехники.

Конечно, возникает вопрос, почему бы просто не использовать Popen с опцией shell = True (ключевое слово)? Это позволит вам передать строку (без разделения и разбора) в оболочку и все равно собрать результаты для обработки по вашему желанию. Мой пример здесь не будет обрабатывать какие-либо конвейеры, обратные ссылки, перенаправление дескриптора файла и т.д., Которые могут быть в команде, все они будут отображаться в виде буквальных аргументов команды. Таким образом, он по-прежнему безопаснее, а затем работает с shell = True... Я дал глупый пример проверки команды на какой-то словарь "одобренной команды" или установил --- через это сделал бы больше смысла нормализовать это до абсолютного пути, если вы не намереваетесь потребовать, чтобы аргументы были нормализованы до передачи командной строки этой функции.