Python 2.6 unter Windows: wie subprocess.Popen mit „shell = True“ Argumente zu beenden?
-
22-08-2019 - |
Frage
Gibt es eine Möglichkeit, einen Prozess begann mit der subprocess.Popen Klasse mit dem „Shell“ Argumente auf „True“ zu beenden? In der Arbeits minimal Beispiel unten (verwendet wxPython) Sie können einen Editor-Prozess glücklich öffnen und beenden, aber wenn Sie die Popen „Shell“ Argument ändern auf „True“, dann wird der Editor-Prozess nicht beenden.
import wx
import threading
import subprocess
class MainWindow(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title)
self.main_panel = wx.Panel(self, -1)
self.border_sizer = wx.BoxSizer()
self.process_button = wx.Button(self.main_panel, -1, "Start process", (50, 50))
self.process_button.Bind(wx.EVT_BUTTON, self.processButtonClick)
self.border_sizer.Add(self.process_button)
self.main_panel.SetSizerAndFit(self.border_sizer)
self.Fit()
self.Centre()
self.Show(True)
def processButtonClick(self, event):
if self.process_button.GetLabel() == "Start process":
self.process_button.SetLabel("End process")
self.notepad = threading.Thread(target = self.runProcess)
self.notepad.start()
else:
self.cancel = 1
self.process_button.SetLabel("Start process")
def runProcess(self):
self.cancel = 0
notepad_process = subprocess.Popen("notepad", shell = False)
while notepad_process.poll() == None: # While process has not yet terminated.
if self.cancel:
notepad_process.terminate()
break
def main():
app = wx.PySimpleApp()
mainView = MainWindow(None, wx.ID_ANY, "test")
app.MainLoop()
if __name__ == "__main__":
main()
Bitte für die Zwecke dieser Frage akzeptieren, dass „Shell“ muss gleich „True“.
Lösung 3
Auf der Grundlage der in Thomas Watnedal Antwort gegeben Spitze, wo er das ist nur die Schale weist darauf hin, tatsächlich in dem Beispiel getötet zu werden, habe ich die folgende Funktion angeordnet, die das Problem für mein Szenario in Mark gegeben, basierend auf dem Beispiel löst Hammonds PyWin32 Bibliothek:
procname ist der Name des Verfahrens, wie in der Task-Manager ohne die Erweiterung gesehen, z.B. Ffmpeg.exe wäre killProcName ( "FFMPEG"). Beachten Sie, dass die Funktion ist relativ langsam, da es Aufzählung aller laufenden Prozesse durchführt, um das Ergebnis nicht sofort ist.
import win32api
import win32pdhutil
import win32con
def killProcName(procname):
"""Kill a running process by name. Kills first process with the given name."""
try:
win32pdhutil.GetPerformanceAttributes("Process", "ID Process", procname)
except:
pass
pids = win32pdhutil.FindPerformanceAttributesByName(procname)
# If _my_ pid in there, remove it!
try:
pids.remove(win32api.GetCurrentProcessId())
except ValueError:
pass
handle = win32api.OpenProcess(win32con.PROCESS_TERMINATE, 0, pids[0])
win32api.TerminateProcess(handle, 0)
win32api.CloseHandle(handle)
Andere Tipps
Warum verwenden Sie shell=True
?
Nur tut es nicht. Sie brauchen es nicht, es ruft die Schale und das ist nutzlos.
Ich akzeptiere nicht, es wird True
hat, weil es nicht. Mit shell=True
bringt Sie nur Probleme und keinen Nutzen. vermeiden Sie es einfach um jeden Preis. Es sei denn, Sie einige Shell-interne Befehl ausführen, Sie brauchen es nicht, immer .
Wenn-Shell = True und den Prozess beenden aufrufen, werden Sie die Schale tatsächlich zu töten, nicht die Notizblock-Prozess. Die Schale würde, was auch immer in dem COMSPEC-Umgebungsvariable angegeben wird.
Die einzige Art, wie ich zu töten diesen Notizblock Prozess denken kann, wäre Win32process.EnumProcesses () zu verwenden, um den Prozess zu suchen, dann töten sie win32api.TerminateProcess verwenden. Sie werden jedoch nicht in der Lage sein, den Notizblock Prozess aus anderen Prozessen mit dem gleichen Namen zu unterscheiden.
Wenn Sie wirklich das shell=True
Flag benötigen, dann ist die Lösung, die den start
Shell-Befehl mit der /WAIT
Flagge zu verwenden. Mit diesem Flag wird der start
Prozess wartet für ihr Kind zu beenden. Dann wird unter Verwendung zum Beispiel des psutil
Modul können Sie erreichen, was Sie wollen mit der folgenden Sequenz:
>>> import psutil
>>> import subprocess
>>> doc = subprocess.Popen(["start", "/WAIT", "notepad"], shell=True)
>>> doc.poll()
>>> psutil.Process(doc.pid).get_children()[0].kill()
>>> doc.poll()
0
>>>
Nach der dritten Zeile erscheint Editor. poll
kehrt None
solange das Fenster offen dank der /WAIT
Flagge ist. Nach der Tötung verschwindet start
des Kindes Editor-Fenster, und poll
gibt den Exit-Code.
Python 2.6 hat eine Kill-Methode für subprocess.Popen Objekte.
http://docs.python.org/library/subprocess .html # subprocess.Popen.kill