2017-01-31 3 views
3

Мы используем процесс python для управления длительными подпроцессами python. Иногда подпроцессы нужно убивать. Команда kill не полностью уничтожает процесс, только делает его несуществующим.Как очистить подпроцессы в python

Выполнение следующего сценария демонстрирует это поведение.

import subprocess 
p = subprocess.Popen(['sleep', '400'], stdout=subprocess.PIPE, shell=False) 

или

p = subprocess.Popen('sleep 400', stdout=subprocess.PIPE, shell=True) 

Создаст подпроцесс.

p.terminate() 
p.kill() 

ничего не делает для этого процесса. Продемонстрировано по ps aux | grep sleep

$ ps aux| grep 'sleep' 
User  8062 0.0 0.0 7292 764 pts/7 S 14:53 0:00 sleep 400 

Процесс не был убит/из несуществующей. С помощью функции subprocess.call() с 'kill' и pid в качестве аргументов выдается команда kill.

subprocess.call(['kill', str(p.pid)]) 

Это убьет процесс, но теперь он уже не функционирует.

$ ps aux | grep 'sleep' 
User  8062 0.0 0.0  0  0 pts/7 Z+ 14:51 0:00 [sleep] <defunct> 

Если очередь работает достаточно долго, он будет в конечном итоге достигнет своего максимального числа процессов, или он будет в конечном итоге пожинать несуществующие процессы и хорошо?

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

Есть ли лучший способ убить процессы?

+1

'kill' только посылает« сигнал »процессу и просит его прекратить его работу. Если вы, однако, «убиваете» его с помощью '-9', его убивает операционная система. Но это считается плохим способом завершения процесса. –

+0

'kill -9' выполняет ту же функцию, что и функция' subprocess.kill() '. Я пытаюсь закончить его с помощью 'p.terminate()' или убить его с помощью 'p.kill()' он все же заканчивается как процесс зомби. – user7495615

ответ

5

Есть 2 основные проблемы здесь:

Первый вопрос: Если вы используете shell=True, так что вы убить оболочки запуска процесса, а не сам процесс. Когда его родитель убит, дочерний процесс перестает/не убивается немедленно.

В вашем случае, вы используете sleep, не встроенный, чтобы вы могли упасть shell=True и Popen даст фактический идентификатор процесса: p.terminate() будет работать.

Вы можете (и вы должны) избегать shell=True большую часть времени, даже если это требует дополнительных питона усилий (ТРУБОПРОВОДНЫЕ 2 команды вместе, перенаправление ввода/вывода кодирования, все эти случаи могут быть хорошо обработаны одним или несколькими Popenбезshell=True.

А (второй вопрос), если процесс все еще несуществующей при завершении после этого исправления, вы могли бы назвать p.wait() (от this вопрос). Кажется, что вызов terminate недостаточно. объект Popen должен быть сбор мусора.

+0

Я попробовал ваше предложение, но оно все еще зомбирует процесс, а не грациозно его убивает. – user7495615

+0

вы пробовали с 'sleep'? Можете ли вы показать свою настоящую команду сейчас? –

+0

Я попробовал это с точным кодом, отправленным в вопрос, и он ведет себя так, как описано. – user7495615

2

после завершения дочернего процесса вы должны позвонить p.wait() - для обработки таблицы операций.Это должно устранить зомби-процессы (в состоянии)

+0

Спасибо, да, это исправляет проблему. – user7495615

+1

, который исправляет проблему (так +1), но только если 'shell = False'. –

+0

согласен, shell = требуется False, поэтому нет оболочки, порожденной python, и она вызывает clone/exec напрямую – VenkatC

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