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... Я дал глупый пример проверки команды на какой-то словарь "одобренной команды" или установил --- через это сделал бы больше смысла нормализовать это до абсолютного пути, если вы не намереваетесь потребовать, чтобы аргументы были нормализованы до передачи командной строки этой функции.