2015-08-26 2 views
4

Я пытаюсь сделать эквивалент следующим использованием подпроцесса Python:как убить группу процессов с помощью Python подпроцесс

>cat /var/log/dmesg | festival --tts & 
[1] 30875 
>kill -9 -30875 

Обратите внимание, что я Уничтожение процесса группу (как обозначено знаком минус добавив идентификационный номер процесса), чтобы убить все детские процессы.

В Python у меня есть следующий код, в котором два процесса создаются и связаны через трубу.

process_cat = subprocess.Popen([ 
    "cat", 
    "/var/log/dmesg" 
], stdout = subprocess.PIPE) 
process_Festival = subprocess.Popen([ 
    "festival", 
    "--tts" 
], stdin = process_cat.stdout, stdout = subprocess.PIPE) 

Как я должен убить эти процессы и их дочерние процессы таким образом, который эквивалентен приведенному выше методу Bash? Следующий подход является недостаточным, поскольку он не убивает дочерние процессы:

os.kill(process_cat.pid, signal.SIGKILL) 
os.kill(process_Festival.pid, signal.SIGKILL) 

есть более элегантный способ сделать это, возможно, используя только один процесс?

+0

Почему недостаточно? Возможно, посмотрите на 'os.setprgid' – betterworld

+0

Это недостаточно, потому что он не убивает дочерние процессы фестиваля. Я отредактирую вопрос для ясности. – d3pd

ответ

11

Вы можете упростить это, так как вам редко требуется cat |. Например:

process_Festival = subprocess.Popen(["festival", "--tts", "/var/log/dmesg"]) 

потом

process_Festival.send_signal(1) 

Если вы убьете фестиваль с сигналом, как SIGHUP, а не SIGKILL его будет убирать любые подпроцессы должным образом.


Там очень хорошее объяснение how to create a new process group с питона подпроцессом. Добавление опции preexec_fn=os.setsid в Popen:

process_Festival = subprocess.Popen(["festival", "--tts", "/var/log/dmesg"],preexec_fn=os.setsid) 

Вы можете получить группу процессов с идентификатором процесса и сигнализировать его:

pgrp = os.getpgid(process_Festival.pid) 
os.killpg(pgrp, signal.SIGINT) 
+0

Привет. Благодарим вас за предложение по упрощению. В этом случае вы совершенно правы (хотя я хочу использовать трубы для других более сложных целей). Что касается вашего подхода '' '' send_signal (9) '' ', проблема в том, что это эквивалентно чем-то вроде' '' kill -9 30875''' в отличие от '' 'kill -9 -30875'''. Ваш подход не убивает многие дочерние процессы, созданные Фестивалем, и это то, что мне нужно. – d3pd

+0

есть 'os.killpg (pg, signal)' и process_Festival.pid - это идентификатор процесса. – meuh

+2

не используйте kill -9, но -1, поэтому фестиваль может очистить своих детей. – meuh