2017-01-31 6 views
3

Wir verwenden einen Python-Prozess, um lange laufende Python-Subprozesse zu verwalten. Teilprozesse müssen gelegentlich getötet werden. Der Befehl kill bringt den Prozess nicht vollständig zum Erliegen, er macht ihn nur ungültig.Subprozesse in Python sauber löschen

Das Ausführen des folgenden Skripts veranschaulicht dieses Verhalten.

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

oder

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

Wird eine subprocess erstellen.

p.terminate() 
p.kill() 

tut nichts zu dem Prozess. Demonstriert von 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 

Der Prozess getötet wurde nicht/gemacht verstorben. Wenn Sie die Funktion subprocess.call() mit 'kill' und pid als Argumente verwenden, wird der Befehl kill ausgegeben.

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

Dies wird den Prozess beenden, aber es ist jetzt nicht mehr gültig.

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

Wenn die Warteschlange läuft lange genug wird es schließlich seine maximale Anzahl von Prozessen erreichen, oder wird es schließlich die nicht mehr existierenden Prozesse ernten und in Ordnung sein?

Wenn die Antwort die erstere ist, wie kann ich mit defekten Prozessen in Python umgehen, ohne den übergeordneten Prozess zu töten?

Gibt es eine bessere Möglichkeit, Prozesse zu töten?

+1

'kill' sendet nur ein" Signal "an den Prozess und fordert sie auf, es zu beenden. Wenn Sie es jedoch mit "-9" "töten", wird es vom Betriebssystem gelöscht. Aber das ist eine schlechte Möglichkeit, einen Prozess zu beenden. –

+0

'kill -9' macht dasselbe wie die' subprocess.kill() 'Funktion. Ob ich versuche, es sauber mit 'p.terminate()' zu beenden oder es mit 'p.kill()' zu beenden, es endet immer noch als Zombie-Prozess. – user7495615

Antwort

5

Es gibt zwei Hauptthemen hier:

Erste Ausgabe: Wenn Sie mit shell=True, so dass Sie die Tötung der Shell den Prozess ausgeführt wird, nicht der Prozess selbst. Wenn der Elternteil getötet wird, geht der Kindprozess verloren oder wird nicht sofort getötet.

In Ihrem Fall, Sie verwenden sleep, die nicht eingebaut ist, so dass Sie shell=True fallen könnten, und Popen würde die eigentliche Prozess-ID ergeben: p.terminate() funktionieren würde.

Sie können (und sollten) vermeiden shell=True die meiste Zeit, auch wenn es Codierungsaufwand zusätzliche Python erfordert (kochend 2 Befehle zusammen, Umleitung Eingabe/Ausgabe, alle diese Fälle durch eine oder mehrere Popen gut gehandhabt werden kann ohneshell=True.

Und (zweite Ausgabe), wenn der Prozess noch nicht mehr existierenden, wenn nach diesem Update beendet, könnten Sie rufen p.wait() (von this Frage). Es scheint, dass terminate Aufruf ist nicht genug. das Popen Objekt sein muss Müll gesammelt

+0

Ich habe deinen Vorschlag ausprobiert, aber es zombiert immer noch den Prozess, anstatt ihn elegant zu töten. – user7495615

+0

hast du es mit 'sleep' versucht? Können Sie jetzt Ihren wirklichen Befehl zeigen? –

+0

Ich versuchte es mit dem genauen Code in der Frage geschrieben und es verhält sich wie beschrieben. – user7495615

2

sollten Sie p.wait() nach Beenden des untergeordneten Prozesses aufrufen - zum Löschen der Prozesstabelle.Das sollte Zombie-Prozesse entfernen (in defunct Zustand)

+0

Danke, ja, das behebt das Problem. – user7495615

+1

das behebt das Problem (also +1) aber nur wenn 'shell = False'. –

+0

stimme zu, shell = False erforderlich, daher gibt es keine Shell, die von Python erzeugt wird und Clone/Exec direkt aufruft – VenkatC

Verwandte Themen