¿Matar proceso por nombre?

99

Estoy tratando de matar un proceso (específicamente iChat). En la línea de comando, uso estos comandos:

ps -A | grep iChat 

Luego:

kill -9 PID

Sin embargo, no estoy exactamente seguro de cómo traducir estos comandos a Python.

Aaron
fuente

Respuestas:

86

Suponiendo que está en una plataforma similar a Unix (para que ps -Aexista),

>>> import subprocess, signal
>>> import os
>>> p = subprocess.Popen(['ps', '-A'], stdout=subprocess.PIPE)
>>> out, err = p.communicate()

le da ps -Ala salida en la outvariable (una cadena). Puede dividirlo en líneas y recorrerlas ...:

>>> for line in out.splitlines():
...   if 'iChat' in line:
...     pid = int(line.split(None, 1)[0])
...     os.kill(pid, signal.SIGKILL)
... 

(podría evitar importar signaly usar en 9lugar de signal.SIGKILL, pero no me gusta particularmente ese estilo, así que prefiero usar la constante nombrada de esta manera).

Por supuesto, podría hacer un procesamiento mucho más sofisticado en estas líneas, pero esto imita lo que está haciendo en shell.

Si lo que busca es evitar ps, eso es difícil de hacer en diferentes sistemas similares a Unix ( pses su API común para obtener una lista de procesos, en cierto sentido). Pero si tiene un sistema específico similar a Unix en mente, solo (que no requiere portabilidad multiplataforma), puede ser posible; en particular, en Linux, el /procpseudo-sistema de archivos es muy útil. Pero deberá aclarar sus requisitos exactos antes de que podamos ayudar en esta última parte.

Alex Martelli
fuente
1
¡Eso funcionó muy bien! Estoy ejecutando un entorno Mac, así que creo que será perfecto. Gracias por toda tu ayuda.
Aaron
Arriba funciona en .nix, pero no es pitónico. La forma adecuada, como se publica a continuación, es utilizar el enfoque os.system ('taskkill / f / im exampleProcess.exe'), que es parte del núcleo de Python.
Jonesome reintegra a Monica
@Jonesome: Su respuesta parece ser para Windows (debido a la sintaxis del comando y el nombre de archivo .exe), pero la pregunta parece ser para Mac OS.
Vasudev Ram
Prefiero esta respuesta a la de Giampaolo Rodolà porque, aunque no es muy Pythonic, funciona en Windows asumiendo que tienes Cygwin o Msys instalados. psutil no está presente en Python 2.7.10 en Windows. Intentar "pip install psutil" falló en mi máquina, diciendo que necesitaba instalar Visual C ++ 9.0. ¡Tornillo que! Prefiero instalar Cygwin o Msys.
Andrew Bainbridge
Funciona en Windows desde Python 3.2, pero normalmente la señal será el código de salida del proceso eliminado.
Cees Timmerman
202

psutil puede encontrar el proceso por nombre y matarlo:

import psutil

PROCNAME = "python.exe"

for proc in psutil.process_iter():
    # check whether the process name matches
    if proc.name() == PROCNAME:
        proc.kill()
Giampaolo Rodolà
fuente
51
Esta. Porque es multiplataforma .
Bengt
2
o si desea por línea de comando algo como: si "your_python_script.py" en proc.cmdline: ..kill
OWADVL
11
La desventaja de esto es que requiere el psutilpaquete, que puede no estar presente en la máquina de destino.
CadentOrange
1
@Bengt. ¡Esto no es multiplataforma si incluye Windows! psutil no es parte de Python 2.7.10. Y "pip install psutil" falla a menos que instale Visual C ++ 9.0, lo que no será práctico en muchos casos. Aún así, felicidades por sus 17 votos a favor :-)
Andrew Bainbridge
5
"pip install psutil" funcionará bien, ya que recuperará la versión de la rueda en pypi. Y no, no necesitas un compilador.
Giampaolo Rodolà
36

Si tiene que considerar el caso de Windows para ser multiplataforma, intente lo siguiente:

os.system('taskkill /f /im exampleProcess.exe')
limitcracker
fuente
@ alansiqueira27 Desafortunadamente, es solo el caso cmd de Windows. Debe ver las respuestas anteriores para las soluciones multiplataforma.
limitcracker
Esto funcionó para mi caso de uso. ¡Gracias! Tenga en cuenta que esto está limpio, mata todos los procesos con ese nombre, por lo que si tiene varios Y.exe que no terminan, todos los ID de proceso se cancelarán.
AlgebraicGeometryStudent
23

Si tienes killall:

os.system("killall -9 iChat");

O:

os.system("ps -C iChat -o pid=|xargs kill -9")
Matthew Flaschen
fuente
9
También está pkill, aunque creo que soy la única persona en el mundo que lo usa en lugar dekillall
Michael Mrozek
1
Está bien, sí, parece que el primer comando funcionó perfectamente. Gracias por la ayuda.
Aaron
1
@MichaelMrozek ¿Cómo puedes vivir con la dulce sensación de escribir cosas como killall java?
Alois Mahdal
@Michael lo uso pkillporque el único killallque conocía era el de "matar todo".
Kyle Strand
7

esto funcionó para mí en Windows 7

import subprocess
subprocess.call("taskkill /IM geckodriver.exe")
d0dulk0
fuente
3

Puedes probar esto. pero antes necesitas instalar psutil usandosudo pip install psutil

import psutil
for proc in psutil.process_iter(attrs=['pid', 'name']):
    if 'ichat' in proc.info['name']:
        proc.kill()
Bakarali Sunasra
fuente
al menos esto es portátil, incluso si la respuesta aceptada ya describe esta solución.
Jean-François Fabre
2

El siguiente código eliminará todos los programas orientados a iChat:

p = subprocess.Popen(['pgrep', '-l' , 'iChat'], stdout=subprocess.PIPE)
out, err = p.communicate()

for line in out.splitlines():        
    line = bytes.decode(line)
    pid = int(line.split(None, 1)[0])
    os.kill(pid, signal.SIGKILL)
Poobalan
fuente
1

Puede usarlo pkill <process_name>en un sistema Unix para matar el proceso por su nombre.

Entonces el código de Python será:

>>> import os
>>> process_name=iChat
>>> os.system('pkill '+process_name)
xaph
fuente
Todos los sistemas que estoy usando son Mac y cuando intento ejecutar pkill solo me dice que no se puede encontrar el comando.
Aaron
1

Si desea eliminar los procesos o cmd.exe que llevan un título en particular.

import csv, os
import subprocess
# ## Find the command prompt windows.
# ## Collect the details of the command prompt windows and assign them.
tasks = csv.DictReader(subprocess.check_output('tasklist /fi "imagename eq cmd.exe" /v /fo csv').splitlines(), delimiter=',', quotechar='"')
# ## The cmds with titles to be closed.
titles= ["Ploter", "scanFolder"]

# ## Find the PIDs of the cmds with the above titles.
PIDList = []
for line in tasks:
    for title in titles:
        if  title in line['Window Title']:
           print line['Window Title']       
           PIDList.append(line['PID'])

# ## Kill the CMDs carrying the PIDs in PIDList
for id in PIDList:
    os.system('taskkill /pid ' + id ) 

Espero eso ayude. Podría haber muchas mejores soluciones a la mía.

Thangasivam Gandhi
fuente
0

puede usar el módulo WMI para hacer esto en Windows, aunque es mucho más torpe de lo que la gente de Unix está acostumbrada; import WMIlleva mucho tiempo y hay un dolor intermedio para llegar al proceso.

un invierno
fuente
0

Para mí lo único que funcionó fue:

Por ejemplo

import subprocess
proc = subprocess.Popen(["pkill", "-f", "scriptName.py"], stdout=subprocess.PIPE)
proc.wait()
Marco Mac
fuente
0

9 representa la señal SIGKILL. Entonces puedes usar KILLen lugar de 9

os.system("kill -s KILL 1234")

0r

os.sytem("kill -KILL 1234")
SuperNova
fuente
0
import os, signal

def check_kill_process(pstring):
    for line in os.popen("ps ax | grep " + pstring + " | grep -v grep"):
        fields = line.split()
        pid = fields[0]
        os.kill(int(pid), signal.SIGKILL)
Abhishek Kumar
fuente
0

La respuesta de Alex Martelli no funcionará en Python 3 porque outserá un objeto de bytes y, por lo tanto, resultará en una TypeError: a bytes-like object is required, not 'str'prueba if 'iChat' in line:.

Citando de la documentación del subproceso :

comunica () devuelve una tupla (stdout_data, stderr_data). Los datos serán cadenas si los flujos se abrieron en modo texto; de lo contrario, bytes.

Para Python 3, esto se resuelve agregando el argumento text=True(> = Python 3.7) o universal_newlines=Trueal Popenconstructor. outluego se devolverá como un objeto de cadena.

import subprocess, signal
import os

p = subprocess.Popen(['ps', '-A'], stdout=subprocess.PIPE, text=True)
out, err = p.communicate()

for line in out.splitlines():
    if 'iChat' in line:
        pid = int(line.split(None, 1)[0])    
        os.kill(pid, signal.SIGKILL)

Alternativamente, puede crear una cadena usando el método decode () de bytes.

import subprocess, signal
import os

p = subprocess.Popen(['ps', '-A'], stdout=subprocess.PIPE)
out, err = p.communicate()

for line in out.splitlines():
    if 'iChat' in line.decode('utf-8'):
        pid = int(line.split(None, 1)[0])    
        os.kill(pid, signal.SIGKILL)
Jason Stoller
fuente
-1
import psutil
pid_list=psutil.get_pid_list()
print pid_list
p = psutil.Process(1052)
print p.name
for i in pid_list:
    p = psutil.Process(i)
    p_name=p.name
    print str(i)+" "+str(p.name)
    if p_name=="PerfExp.exe":
        print "*"*20+" mam ho "+"*"*20
        p.kill()
peterik
fuente