Убийство подпроцесса Python - PullRequest
5 голосов
/ 14 августа 2011

У меня проблема с уничтожением подпроцессов. Следующий фрагмент кода используется для создания подпроцесса -

  while(not myQueue.empty()): 
        p=Popen(myQueue.get(),shell=True,stdin=PIPE,stderr=PIPE)

Я создаю процессы путем итерации, пока очередь (в которой есть команды) не станет пустой. Переменная p является глобальной и является объектом типа Popen. Несмотря на то, что команда сделала то, что должна, у меня возникли проблемы с кнопкой остановки, которая не останавливает процесс, как я ожидал.

Код кнопки останова следующий:

  stop=Button(textBoxFrame,text="Stop",width=5,command=stopAll)
  stop.grid(row=1,column=4)

Метод stopAll вызывается вышеуказанной кнопкой остановки, которая убивает текущий подпроцесс p.

  def stopAll():
        p.kill()

ПРИМЕЧАНИЕ. - Нет ошибок, исключений или проблем с компиляцией.

UPDATE: Проблема в том, что p.kill() не убивал процесс, который мне нужно было убить. Я проверил это с Unix, используя >> ps aux. Я также сделал свою программу для вывода стартовых и убивающих PID, чтобы я мог проверить их с помощью ps aux. Я обнаружил, что процесс, который мне нужно убить, был на расстоянии 6 PID от p.pid, я попытался убить процесс, например os.kill((p.pid)+6,signal.SIGKILL), который работает и остановил правильный процесс. Но я не хочу так поступать, поскольку есть вероятность, что различные дочерние процессы могут быть убиты. Я даю более подробную информацию о моей проблеме-

Очередь, которую я здесь использую, содержит команды, как я уже говорил ранее. Команда примерно такая:

    echo "Hello"|festival --tts

Festival - это синтезатор речи в Unix, и festival --tts получает пользовательский ввод из файла. Я пишу "Hello" на фестиваль, и он правильно произносит слова. Но p, который является процессом выполнения вышеупомянутой команды, убивает echo, а не festival. Поэтому, пожалуйста, помогите мне с убийством определенного (фестивального) процесса.

Ответы [ 4 ]

1 голос
/ 14 августа 2011

Я подозреваю, что у вас могут быть проблемы, поскольку вы не объявляете stopPressed внутри своей функции stopAll () как глобальную, например,

>>> fred = '20'
>>> def updateFred(age):
...     fred=age
>>> updateFred(40)
>>> fred
'20'
>>> def updateFred(age):
...     global fred
...     fred=age
>>> updateFred(40)
>>> fred
40

Возможно добавление 'global stopPressed' в начале stopAll) поможет?

0 голосов
/ 16 августа 2011

Поскольку программа фестиваля в UNIX, мы можем использовать preexec_fn.Фестиваль создавал свои собственные подпроцессы, которые усложняли убийство, поэтому в этом случае использование идентификатора группы, который идентифицирует все фестивальные процессы, решит эту проблему.Мы можем создать группу процессов, используя приведенный ниже код:

   while(not myQueue.empty()): 
    p=Popen(myQueue.get(),shell=True, stdin=PIPE,preexec_fn=os.setsid)

stopAll теперь имеет следующий код для уничтожения группы дочерних процессов, указанных в глобальной переменной: p-

    os.killpg(os.getpgid(p.pid), signal.SIGKILL)

killгруппа подпроцессов, которые порождаются.Источник: Работа с подпроцессом

0 голосов
/ 15 августа 2011

Как уже упоминалось @aid, если вы не сделаете излишним глобальный дескриптор, вы не сможете изменить его для всех остальных.Попробуйте это вместо вашей функции stopAll

def stopAll():
    global stopPressed
    stopPressed=True

Я бы предложил вместо того, чтобы связываться с глобальными переменными, а не создавать класс, такой как

class GuiController(object):
    # if you want the stopPressed to be a static variable accross all
    # GuiController instances uncomment the next line and comment out the __init__
    #stopPressed = False
    def __init__(self):
        self.stopPressed=False
    def main(self):
        while(not myQueue.empty()): 
            p=Popen(myQueue.get(),shell=True,stdin=PIPE,stderr=PIPE)
            while(p.returncode==None):
                if(stopPressed==True):
                    p.kill()
                    break
        self.stopPressed=False
    def stopAll(self):
        self.stopPressed=True
0 голосов
/ 14 августа 2011

Я думаю, что нужно больше кода. Я не уверен, как вы обрабатываете событие нажатия кнопки (подозревая проблему с многопоточностью). Кроме того, разве не следует включать пробки внутри первого цикла, а не снаружи? проблема пробелов (или проблема только здесь?).

...