Question

Je lance un sous-processus avec la commande suivante:

p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)

Cependant, lorsque je tente de tuer en utilisant:

p.terminate()

ou

p.kill()

La commande continue à fonctionner en arrière-plan, donc je me demandais comment puis-je mettre fin à fait le processus.

Notez que lorsque je lance la commande avec:

p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE)

Il ne se termine avec succès lors de l'émission du p.terminate().

Était-ce utile?

La solution

Utilisation d'un groupe de processus de manière à permettre l'envoi d'un signal à tous les processus dans les groupes . Pour cela, vous devez joindre une id session, au processus parent du donné naissance / processus enfants, ce qui est une coquille dans votre cas. Il sera le chef de groupe des processus. Alors maintenant, quand un signal est envoyé au chef de groupe de processus, il est transmis à tous les processus enfants de ce groupe.

Voici le code:

import os
import signal
import subprocess

# The os.setsid() is passed in the argument preexec_fn so
# it's run after the fork() and before  exec() to run the shell.
pro = subprocess.Popen(cmd, stdout=subprocess.PIPE, 
                       shell=True, preexec_fn=os.setsid) 

os.killpg(os.getpgid(pro.pid), signal.SIGTERM)  # Send the signal to all the process groups

Autres conseils

p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
p.kill()

p.kill() extrémités par tuer le processus de coquille et cmd est encore en cours d'exécution.

J'ai trouvé une solution pratique en:

p = subprocess.Popen("exec " + cmd, stdout=subprocess.PIPE, shell=True)

Cela entraînera cmd pour hériter du processus shell, au lieu d'avoir le lancement de la coquille d'un processus enfant, qui ne soit pas tué. p.pid sera l'ID de votre processus cmd puis.

p.kill() devrait fonctionner.

Je ne sais pas quel effet cela aura sur votre pipe bien.

Si vous pouvez utiliser psutil , cela fonctionne parfaitement:

import subprocess

import psutil


def kill(proc_pid):
    process = psutil.Process(proc_pid)
    for proc in process.children(recursive=True):
        proc.kill()
    process.kill()


proc = subprocess.Popen(["infinite_app", "param"], shell=True)
try:
    proc.wait(timeout=3)
except subprocess.TimeoutExpired:
    kill(proc.pid)

Je pourrais le faire en utilisant

from subprocess import Popen

process = Popen(command, shell=True)
Popen("TASKKILL /F /PID {pid} /T".format(pid=process.pid))

il a tué le cmd.exe et le programme que j'ai donné la commande pour.

(sous Windows)

Lorsque shell=True la coquille est le processus de l'enfant, et les commandes sont ses enfants. Ainsi, toute SIGTERM ou SIGKILL tueront la coque mais non ses processus enfants, et je ne me rappelle pas une bonne façon de le faire. La meilleure façon que je peux penser est d'utiliser shell=False, sinon quand vous tuez le processus de shell parent, il laissera un processus shell défunte.

Aucune de ces réponses travaillé pour moi si Im laissant le code qui a fait le travail. Dans mon cas, même après avoir tué le processus avec .kill() et obtenir un code de retour de .poll() le processus n'a pas mis fin.

Suite à la subprocess.Popen documentation :

« ... pour le nettoyage correctement une application bien comportés devrait tuer le processus de l'enfant et de la communication finale ... »

proc = subprocess.Popen(...)
try:
    outs, errs = proc.communicate(timeout=15)
except TimeoutExpired:
    proc.kill()
    outs, errs = proc.communicate()

Dans mon cas, je manquais le proc.communicate() après avoir appelé proc.kill(). Ceci nettoie le processus stdin, stdout ... et ne se termine le processus.

Comme Sai dit, la coquille est l'enfant, de sorte que les signaux sont interceptés par elle - meilleure façon que je l'ai trouvé est d'utiliser shell = False shlex et utiliser pour diviser la ligne de commande:

if isinstance(command, unicode):
    cmd = command.encode('utf8')
args = shlex.split(cmd)

p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

Alors p.kill () et p.terminate () devrait fonctionner comment vous vous attendez.

ce que je ressens que nous pourrions utiliser:

import os
import signal
import subprocess
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)

os.killpg(os.getpgid(pro.pid), signal.SIGINT)

ce ne sera pas tuer votre tâche, mais le processus avec le p.pid

Je sais que c'est une question ancienne mais quelqu'un d'aide peut la recherche d'une autre méthode. Voilà ce que j'utilise sur les fenêtres pour tuer les processus que je l'ai appelé.

si = subprocess.STARTUPINFO()
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
subprocess.call(["taskkill", "/IM", "robocopy.exe", "/T", "/F"], startupinfo=si)

/ IM est le nom de l'image, vous pouvez également faire / PID si vous voulez. / T tue le processus ainsi que les processus enfants. / F Force la termine. si, comme je l'ai mis, comment vous faites cela sans montrer une fenêtre CMD. Ce code est utilisé en Python 3.

Envoyer le signal à tous les processus dans le groupe

    self.proc = Popen(commands, 
            stdout=PIPE, 
            stderr=STDOUT, 
            universal_newlines=True, 
            preexec_fn=os.setsid)

    os.killpg(os.getpgid(self.proc.pid), signal.SIGHUP)
    os.killpg(os.getpgid(self.proc.pid), signal.SIGTERM)

Je n'ai pas vu cette mention ici, donc je le mets là au cas où quelqu'un a besoin. Si tout ce que vous voulez faire est de vous assurer que votre sous-processus se termine avec succès, vous pouvez le mettre dans un gestionnaire de contexte. Par exemple, je voulais que mon imprimante standard pour imprimer une image sur et en utilisant le gestionnaire de contexte assuré que le sous-processus terminé.

import subprocess

with open(filename,'rb') as f:
    img=f.read()
with subprocess.Popen("/usr/bin/lpr", stdin=subprocess.PIPE) as lpr:
    lpr.stdin.write(img)
print('Printed image...')

Je crois que cette méthode est également multi-plateforme.

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