Domanda

C'è un modo per terminare un processo avviato con la classe subprocess.Popen con l'argomento "guscio" impostato su "True"? Nel lavoro minima esempio sotto (usa wxPython) è possibile aprire e terminare un processo Blocco felicemente, se si modifica l'argomento Popen "shell" a "True" allora il processo Blocco non termina.

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()

Si prega di accettare per il bene di questa domanda che "guscio" non deve essere uguale "True".

È stato utile?

Soluzione 3

In base alla punta, indicato nella risposta di Thomas Watnedal, dove egli sottolinea che solo il guscio sia effettivamente ucciso nella esempio, ho disposto la seguente funzione che risolve il problema per il mio scenario, sulla base l'esempio dato in Marco biblioteca PyWin32 di Hammond:

nomeproc è il nome del processo come visto in Task Manager senza l'estensione, ad esempio Ffmpeg.exe sarebbe killProcName ( "FFMPEG"). Si noti che la funzione è ragionevolmente lento come esegue l'enumerazione di tutti i processi in esecuzione in corso in modo che il risultato non è immediato.

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)

Altri suggerimenti

Perché stai usando shell=True?

Basta non farlo. Non è necessario, esso invoca il guscio e che è inutile.

Non accettare deve essere True, perché non è così. Utilizzando shell=True si porta solo problemi e nessun beneficio. Basta evitare a tutti i costi. A meno che non si sta eseguendo un comando interno di shell, non è necessario che, mai .

Quando si utilizza shell = True e chiamando terminare il processo, in realtà si sta uccidendo il guscio, non il processo blocco note. Il guscio sarà qualunque viene specificata nella variabile di ambiente COMSPEC.

L'unico modo che posso pensare di uccidere questo processo notepad sarebbe quella di utilizzare Win32process.EnumProcesses () per cercare il processo, poi uccidete utilizzando win32api.TerminateProcess. Potrai comunque non essere in grado di distinguere il processo di blocco note da altri processi con lo stesso nome.

Se si ha realmente bisogno la bandiera shell=True, allora la soluzione è quella di utilizzare il comando di shell start con la bandiera /WAIT. Con questo flag, il processo start attenderà la sua bambina per terminare. Poi, usando per esempio il psutil modulo è possibile ottenere ciò che si vuole con la seguente sequenza:

>>> 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
>>> 

Dopo la terza linea appare Blocco note. ritorna poll None fino a quando la finestra è aperta grazie alla bandiera /WAIT. Dopo aver ucciso finestra del Blocco note figlio di start scompare, e poll restituisce il codice di uscita.

Python 2.6 ha un metodo uccidere per gli oggetti subprocess.Popen.

http://docs.python.org/library/subprocess .html # subprocess.Popen.kill

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top