Question

Est-il possible de mettre fin à un processus commencé avec la classe subprocess.Popen avec l'argument « shell » à « true »? Dans l'exemple ci-dessous un minimum de travail (utilise wxPython), vous pouvez ouvrir et mettre fin à un processus Notepad heureusement, si vous changez l'argument Popen « shell » pour ensuite « True » le processus de Bloc-notes ne se termine pas.

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

S'il vous plaît accepter au nom de cette question que « coquille » n'égale à « True ».

Était-ce utile?

La solution 3

Sur la base de donnée dans la réponse de Thomas Watnedal, où il a fait remarquer que seulement la coquille est réellement tué dans l'exemple, je me suis arrangé la fonction suivante qui permet de résoudre le problème pour mon scénario, basé sur l'exemple donné à Mark la bibliothèque pywin32 de Hammond:

procname est le nom du procédé tel que vu dans le gestionnaire de tâches sans l'extension, par exemple, Ffmpeg.exe serait killProcName ( "FFMPEG"). Notez que la fonction est raisonnablement lent car il effectue l'énumération de tous les processus de fonctionnement actuels de sorte que le résultat n'est pas instantanée.

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)

Autres conseils

Pourquoi utilisez-vous shell=True?

Il suffit de ne pas le faire. Vous n'avez pas besoin, il invoque la coquille et qui est inutile.

Je ne l'accepte pas doit être True, parce qu'il ne fonctionne pas. L'utilisation shell=True vous apporte seulement des problèmes et aucun avantage. Il suffit d'éviter à tout prix. À moins que vous exécutez une commande interne du shell, vous n'avez pas besoin, jamais .

Lorsque vous utilisez shell = True et appelant terminer le processus, vous tuez effectivement la coquille, pas le processus de bloc-notes. La coque serait tout est spécifié dans la variable d'environnement COMSPEC.

La seule façon que je peux penser à tuer ce processus notepad serait d'utiliser Win32process.EnumProcesses () pour rechercher le processus, puis le tuer en utilisant win32api.TerminateProcess. Il vous sera toutefois pas en mesure de distinguer le processus de bloc-notes des autres processus du même nom.

Si vous avez vraiment besoin le drapeau shell=True, la solution est d'utiliser la commande shell start avec le drapeau de /WAIT. Avec ce drapeau, le processus de start attendra son enfant de mettre fin. Puis, en utilisant par exemple le module psutil vous pouvez obtenir ce que vous voulez avec la séquence suivante:

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

Après la troisième ligne Bloc-notes apparaît. retourne poll None tant que la fenêtre est ouverte grâce au drapeau /WAIT. Après avoir tué la fenêtre Bloc-notes de l'enfant de start disparaît, et poll renvoie le code de sortie.

Python 2.6 a une méthode de mise à mort pour les objets subprocess.Popen.

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

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top