Pregunta

¿Hay una manera de terminar un proceso iniciado con la clase subprocess.Popen con el argumento de "concha" en "True"? En el ejemplo a continuación un mínimo de trabajo (utiliza wxPython) se puede abrir y poner fin a un proceso de Bloc de notas con alegría, sin embargo, si cambia el argumento Popen "cáscara" a "True", entonces el proceso de Bloc de notas no 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()

Por favor, acepte por el bien de esta cuestión que "cáscara" tiene que ser igual a "True".

¿Fue útil?

Solución 3

Sobre la base de la punta que figuran en la respuesta de Thomas Watnedal, donde se señala que sólo la cáscara está siendo realmente murió en el ejemplo, he dispuesto la siguiente función que resuelve el problema de mi escenario, basado en el ejemplo dado en Marcos pywin32 biblioteca de Hammond:

procname es el nombre del proceso como se ve en el Administrador de tareas sin la extensión, por ejemplo, Ffmpeg.exe sería killProcName ( "FFMPEG"). Tenga en cuenta que la función es bastante lento, ya que lleva a cabo la enumeración de todos los procesos en ejecución actuales por lo que el resultado no es inmediato.

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)

Otros consejos

¿Por qué utiliza shell=True?

Pero no hacerlo. Usted no lo necesita, se invoca la cáscara y que es inútil.

No aceptar que tiene que ser True, porque no lo hace. Usando shell=True sólo le trae problemas y ningún beneficio. Sólo evitar a toda costa. A menos que esté ejecutando algún comando interno de la cáscara, que no lo necesita, nunca .

Cuando se utiliza la cáscara = true y llamando a terminar en el proceso, en realidad se está matando a la cáscara, no el proceso de bloc de notas. La cáscara se lo está especificado en la variable de entorno COMSPEC.

La única manera que puedo pensar de matar a este proceso el bloc de notas sería utilizar Win32process.EnumProcesses () para buscar el proceso, entonces matarlo usando win32api.TerminateProcess. No obstante, usted no será capaz de distinguir el proceso de libreta de otros procesos con el mismo nombre.

Si realmente necesita la bandera shell=True, entonces la solución es utilizar el comando shell start con la bandera /WAIT. Con este indicador, el proceso de start esperará a que su hijo termine. Luego, utilizando por ejemplo el psutil módulo se puede lograr lo que quiere con la siguiente secuencia:

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

Después de la tercera línea aparece el Bloc de notas. vuelve poll None siempre y cuando la ventana está abierta gracias a la bandera /WAIT. Después de matar desaparece ventana Bloc de notas de niño start y poll devuelve el código de salida.

Python 2.6 tiene un método de interrupción para objetos subprocess.Popen.

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top