有没有一种方法可以终止以subprocess.Popen类开头且“ shell”参数设置为“ True”的进程?在下面的最小工作示例(使用wxPython)中,您可以愉快地打开和终止记事本进程,但是,如果将Popen的“ shell”参数更改为“ True”,则记事本进程不会终止。
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()
为了这个问题,请接受“ shell”必须等于“ True”。
根据Thomas Watnedal的回答中的提示,他指出示例中实际上只是外壳被杀死,我根据Mark Hammond的PyWin32库中给出的示例,安排了以下函数来解决我的方案的问题。 :
procname是在任务管理器中看到的没有扩展名的进程的名称,例如FFMPEG.EXE将是killProcName(“ FFMPEG”)。请注意,该函数相当慢,因为它对所有当前正在运行的进程进行枚举,因此结果不是即时的。
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)