2013-05-31 4 views
11

Sto lanciando un programma con subprocess su Python.Uccidere una chiamata di sottoprocesso in esecuzione

In alcuni casi il programma potrebbe bloccarsi. Questo è fuori dal mio controllo. L'unica cosa che posso fare dalla riga di comando da cui viene lanciato è CtrlEsc che uccide rapidamente il programma.

C'è un modo per emulare questo con subprocess? Sto usando subprocess.Popen(cmd, shell=True) per avviare il programma.

risposta

15
p = subprocess.Popen("echo 'foo' && sleep 60 && echo 'bar'", shell=True) 
p.kill() 

Scopri i documenti sul modulo subprocess per maggiori informazioni: http://docs.python.org/2/library/subprocess.html

+2

Probabilmente dovrebbe provare a terminare prima di ucciderlo completamente. – Gewthen

+1

Provato terminare e quindi uccidere, il sottoprocesso funziona ancora !! – hungryWolf

+0

probabilmente a causa di shell = True –

20

Beh, ci sono un paio di metodi per l'oggetto restituito da subprocess.Popen() che possono essere di uso: Popen.terminate() e Popen.kill(), che inviano a SIGTERM e SIGKILL rispettivamente.

Ad esempio ...

import subprocess 
import time 

process = subprocess.Popen(cmd, shell=True) 
time.sleep(5) 
process.terminate() 

... sarebbe terminare il processo dopo cinque secondi.

Oppure è possibile utilizzare os.kill() per inviare altri segnali, come SIGINT per simulare CTRL-C, con ...

import subprocess 
import time 
import os 
import signal 

process = subprocess.Popen(cmd, shell=True) 
time.sleep(5) 
os.kill(process.pid, signal.SIGINT) 
+2

Su Windows 'kill = terminate' ei segnali non funzionano allo stesso modo. – jfs

1

La tua domanda non è troppo chiaro, ma se suppongo che si sta per lancio un processo che va a zombie e vuoi essere in grado di controllarlo in qualche stato del tuo script. Se questo caso, vi propongo il seguente:

p = subprocess.Popen([cmd_list], shell=False) 

Questo in realtà non le nostre raccomandazioni di passare attraverso il guscio. Ti suggerirei di usare shell = False, in questo modo rischierai meno un overflow.

# Get the process id & try to terminate it gracefuly 
pid = p.pid 
p.terminate() 

# Check if the process has really terminated & force kill if not. 
try: 
    os.kill(pid, 0) 
    p.kill() 
    print "Forced kill" 
except OSError, e: 
    print "Terminated gracefully" 
+0

- p.pid è una proprietà delle istanze Popen, non un metodo - Quando viene sollevato esattamente l'errore OSError? Anche per le chiamate Popen semplici (subprocess.Popen ("ls", shell = False)) Non riesco a ottenere l'istruzione except. – bergercookie

+0

è giusto, pid è una proprietà, dovrebbe essere un errore di battitura. Per OSError, l'eccezione viene sollevata al passo os.kill (pid, 0) se il pid non esiste più - p.terminate() ha terminato il pid con successo ;-) – ScotchAndSoda

0

È possibile utilizzare due segnali per uccidere un running sottoprocesso chiamare cioè signal.SIGTERM e signal.SIGKILL; per esempio

import subprocess 
import os 
import signal 
import time 
.. 
process = subprocess.Popen(..) 
.. 
# killing all processes in the group 
os.killpg(process.pid, signal.SIGTERM) 
time.sleep(2) 
if process.poll() is None: # Force kill if process is still alive 
    time.sleep(3) 
    os.killpg(process.pid, signal.SIGKILL)