2012-04-23 2 views
1

Я уже несколько дней борюсь с Popen на python, поэтому решил все мои сомнения, надеюсь, все они могут быть разъяснены экспертами python.python Popen: Как заблокировать выполнение команды grep до тех пор, пока содержимое grep не будет готово?

Первоначально я использую Popen для выполнения команды и grep результат (как одна команда с использованием pipe, что-то вроде xxx | grep yyy), с shell=False, как вы можете себе представить, это не работает. После руководство в this посте я изменил код к следующему:

checkCmd = ["sudo", "pyrit", "-r", self.capFile, "analyze"] 
checkExec = Popen(checkCmd, shell=False, stdout=PIPE, stderr=STDOUT) 
grepExec = Popen(["grep", "good"], stdin=checkExec.stdout, stdout=PIPE) 
output = grepExec.stdout.readline() 
output = grepExec.communicate()[0] 

Но я понял, что checkExec работает медленно и с тех Popen неблокирующая, grepExec всегда получают выполняться до checkExec показывает какой-либо результат, таким образом, Выход grep всегда будет пустым. Как отложить выполнение grepExec до checkExec?

  1. В другой программе Popen в моей программе я попытался сохранить сервис на задней панели, поэтому я использую отдельный поток для его выполнения. Когда все задачи выполняются, я уведомляю этот поток о завершении работы, и я просто вызываю Popen.kill(), чтобы остановить службу. Однако моя система заканчивается процессом зомби, который не получил. Я не знаю, есть ли хороший способ очистить все в этом фоновом потоке после его завершения?

  2. В чем разница между Popen.communicate() [0] и Popen.stdout.readline()? Могу ли я использовать цикл для чтения вывода данных из обоих?

+0

Есть ли конкретная причина, по которой вы не хотите использовать функциональные возможности оболочки оболочки? (с '|') – mensi

+0

@mensi: Я указал shell = False, поэтому труба может не работать. Вначале я пробовал трубу в shell = False, но Popen выполняет команду без grep после этого. –

+0

@mensi есть много веских причин, чтобы ваш «Popen» не создавал подоболочку - выполняя прямой сценарий «execv()» из вашего скрипта, означает, что вам не нужно указывать аргументы, которые нужно проанализировать оболочка, как вы ожидаете, которая может быть очень большой сделкой с точки зрения безопасности, если она содержит данные, созданные пользователем. –

ответ

4

Ваш пример будет работать, если вы делаете это так:

checkCmd = ["sudo", "pyrit", "-r", self.capFile, "analyze"] 
checkExec = Popen(checkCmd, shell=False, stdout=PIPE, stderr=STDOUT) 
grepExec = Popen(["grep", "good"], stdin=checkExec.stdout, stdout=PIPE) 

for line in grepExec.stdout: 
    # do something with line 

Вы используете сообщаться, когда вы хотите, чтобы дать некоторый вклад в процесс и читать весь вывод на стандартный вывод, STDERR процесса в в то же время. Вероятно, это не то, что вы хотите для своего дела. communicate больше подходит для случаев, когда вы хотите запустить приложение, подать все необходимые ему данные и прочитать его вывод.

Как и другие ответы отметили, вы можете использовать shell=True для создания трубопровода в вашем призыве к подпроцессу, но альтернатива, которую я предпочел бы, чтобы использовать питон и вместо создании трубопровода делает:

checkCmd = ["sudo", "pyrit", "-r", self.capFile, "analyze"] 
checkExec = Popen(checkCmd, shell=False, stdout=PIPE, stderr=STDOUT) 
for line in checkExec.stdout: 
    if line.find('good') != -1: 
     do something with the matched line here 
2

Используйте подпроцесс вместо popen, тогда вы можете значительно упростить ситуацию с помощью всей командной строки.

http://docs.python.org/library/subprocess.html

например.

import subprocess as sub 
f = open('/dev/null', 'w') 
proc = sub.call("cat file | grep string", executable="/bin/bash", shell=True) 
+1

В простом случае этот подход может быть проще, но сложнее получить право при сборке командной строки с пользовательских входов - если строка grepped для пользователя создается, например, чем в этом случае должна быть указана цитата ... но _not_ при использовании 'Popen' с массивом и без' shell = True'. –

+0

Я предполагаю, что в этом случае я не могу сохранить вывод в своей программе, верно? –

+0

@da_zhuang с этим конкретным синтаксисом, да, я просто вытащил один из скрипта, который я использую. Вы хотите использовать метод 'subprocess.check_output'. И сборка командной строки с пользовательского ввода тривиальна, используя обычные методы, отформатированные строки печати в присваивании переменных, подстановку переменных и т. Д. Я не вдавался в подробности вашего конкретного случая, так как на странице документов есть вся информация и пример необходимость. – TaoJoannes

Смежные вопросы