Ich starte einen Unterprozess mit dem folgenden Befehl:
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
Wenn ich jedoch versuche zu töten mit:
p.terminate()
oder
p.kill()
Der Befehl wird weiterhin im Hintergrund ausgeführt, daher habe ich mich gefragt, wie ich den Prozess tatsächlich beenden kann.
Beachten Sie Folgendes, wenn ich den Befehl ausführe mit:
p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)
Es wird erfolgreich beendet, wenn das ausgegeben wird p.terminate()
.
python
linux
subprocess
kill-process
user175259
quelle
quelle
cmd
siehst du aus? Es kann einen Befehl enthalten, der das Starten mehrerer Prozesse auslöst. Es ist also nicht klar, über welchen Prozess Sie sprechen.shell=True
großen Unterschied?Antworten:
Verwenden Sie eine Prozessgruppe , um das Senden eines Signals an alle Prozesse in den Gruppen zu ermöglichen. Dazu sollten Sie dem übergeordneten Prozess der erzeugten / untergeordneten Prozesse eine Sitzungs-ID hinzufügen, die in Ihrem Fall eine Shell ist. Dies macht es zum Gruppenleiter der Prozesse. Wenn nun ein Signal an den Prozessgruppenleiter gesendet wird, wird es an alle untergeordneten Prozesse dieser Gruppe übertragen.
Hier ist der Code:
quelle
os.setsid
es in Windows nicht verfügbar ist ( docs.python.org/library/os.html#os.setsid ), weiß ich nicht, ob dies helfen kann, aber Sie können hier nachsehen ( bugs.python.org) / issue5115 ) für einen Einblick, wie es geht.subprocess.CREATE_NEW_PROCESS_GROUP
das damit zusammen?CREATE_NEW_PROCESS_GROUP
kann verwendet werden, umstart_new_session=True
unter Windows zu emulierenp.kill()
beendet den Shell-Prozess undcmd
läuft noch.Ich fand eine bequeme Lösung, indem ich:
Dies führt dazu, dass cmd den Shell-Prozess erbt, anstatt dass die Shell einen untergeordneten Prozess startet, der nicht beendet wird.
p.pid
wird dann die ID Ihres cmd-Prozesses sein.p.kill()
sollte arbeiten.Ich weiß allerdings nicht, welche Auswirkungen dies auf Ihre Pfeife haben wird.
quelle
Wenn Sie Psutil verwenden können , funktioniert dies perfekt:
quelle
AttributeError: 'Process' object has no attribute 'get_children
fürpip install psutil
.Ich könnte es mit tun
es tötete das
cmd.exe
und das Programm, für das ich den Befehl gab.(Unter Windows)
quelle
Popen("TASKKILL /F /IM " + process_name)
Wenn Sie ihn nicht haben, können Sie ihn über dencommand
Parameter abrufen.Wenn
shell=True
die Shell der untergeordnete Prozess ist und die Befehle ihre untergeordneten Prozesse sind. Also jederSIGTERM
oderSIGKILL
wird die Shell töten, aber nicht ihre untergeordneten Prozesse, und ich erinnere mich nicht an einen guten Weg, dies zu tun. Der beste Weg, den ich mir vorstellen kann, ist die Verwendungshell=False
. Andernfalls wird beim Beenden des übergeordneten Shell-Prozesses ein nicht mehr funktionierender Shell-Prozess zurückgelassen.quelle
Keine dieser Antworten hat bei mir funktioniert, also lasse ich den Code, der funktioniert hat. In meinem Fall wurde der Prozess auch nach dem Beenden des Prozesses mit
.kill()
und dem Abrufen eines.poll()
Rückkehrcodes nicht beendet.Befolgen Sie die
subprocess.Popen
Dokumentation :In meinem Fall fehlte mir das
proc.communicate()
nach dem Anrufproc.kill()
. Dies bereinigt den Prozess stdin, stdout ... und beendet den Prozess.quelle
Wie Sai sagte, ist die Shell das Kind, also werden Signale von ihr abgefangen - der beste Weg, den ich gefunden habe, ist Shell = False zu verwenden und Shlex zu verwenden, um die Befehlszeile zu teilen:
Dann sollten p.kill () und p.terminate () so funktionieren, wie Sie es erwarten.
quelle
cwd
Argument einfach an weiterPopen
.Wie ich denke, könnten wir gebrauchen:
Dies wird nicht alle Ihre Aufgaben beenden, sondern den Prozess mit der p.pid
quelle
Ich weiß, dass dies eine alte Frage ist, aber dies kann jemandem helfen, der nach einer anderen Methode sucht. Dies ist, was ich unter Windows verwende, um Prozesse abzubrechen, die ich aufgerufen habe.
/ IM ist der Bildname, Sie können auch / PID ausführen, wenn Sie möchten. / T beendet den Prozess sowie die untergeordneten Prozesse. / F Kraft beendet es. si, wie ich es eingestellt habe, ist, wie Sie dies tun, ohne ein CMD-Fenster anzuzeigen. Dieser Code wird in Python 3 verwendet.
quelle
Senden Sie das Signal an alle Prozesse in der Gruppe
quelle
Ich habe dies hier nicht erwähnt gesehen, also stelle ich es dort heraus, falls jemand es braucht. Wenn Sie lediglich sicherstellen möchten, dass Ihr Unterprozess erfolgreich beendet wird, können Sie ihn in einen Kontextmanager einfügen. Ich wollte beispielsweise, dass mein Standarddrucker ein ausgedrucktes Bild druckt und mithilfe des Kontextmanagers sicherstellt, dass der Unterprozess beendet wird.
Ich glaube, diese Methode ist auch plattformübergreifend.
quelle
shell=True
, gemäß der Frage? Was es nicht in Ihrem Code ist.thread.join()
. Hoffe das klärt es auf.