2013-05-31 19 views
11

Uruchamiam program z subprocess na Pythonie.Utrata działającego wywołania podprocesowego

W niektórych przypadkach program może się zawiesić. To jest poza moją kontrolą. Jedyne, co mogę zrobić z wiersza poleceń, to jest uruchamiany od CtrlEsc, który szybko zabija program.

Czy istnieje sposób na emulowanie tego z subprocess? Używam subprocess.Popen(cmd, shell=True) do uruchomienia programu.

Odpowiedz

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

Wyjazd docs na module subprocess aby uzyskać więcej informacji: http://docs.python.org/2/library/subprocess.html

+2

Prawdopodobnie powinien spróbować zakończyć, zanim zabije go całkowicie. – Gewthen

+1

Próbowałem zakończyć, a następnie zabić, podprocesować nadal działa !! – hungryWolf

+0

prawdopodobnie z powodu powłoki = True –

20

Cóż, istnieje kilka metod na obiekcie zwróconym przez subprocess.Popen(), które mogą być przydatne: Popen.terminate() i Popen.kill(), które wysyłają odpowiednio: SIGTERM i SIGKILL.

Na przykład ...

import subprocess 
import time 

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

... by zakończyć proces po pięciu sekundach.

Albo można użyć os.kill() wysyłać inne sygnały, jak SIGINT symulować CTRL-C, z ...

import subprocess 
import time 
import os 
import signal 

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

W systemie Windows 'kill = endate' i sygnały nie działają w ten sam sposób. – jfs

1

Twoje pytanie nie jest zbyt jasne, ale jeśli przyjąć, że masz zamiar uruchomienia proces, który idzie do zombie i chcesz mieć możliwość kontrolowania tego w jakimś stanie twojego skryptu. Jeśli tak jest w przypadku, proponuję Ci następujące:

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

To naprawdę nie polecił przejść przez powłokę. Proponuję, żebyś użył powłoki = False, w ten sposób ryzykujesz mniejszą przepełnią.

# 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 jest własnością instancji Popen, a nie metodą. - Kiedy dokładnie jest podnoszony OSError? Nawet dla prostych wywołań Popen (subprocess.Popen ("ls", shell = False)) nie mogę dostać się do instrukcji except. – bergercookie

+0

To prawda, pid jest właściwością, powinien to być błąd literowy. Dla OSError wyjątek jest podnoszony w kroku os.kill (pid, 0), jeśli pid już nie istnieje - p.terminate() zakończyło pid z powodzeniem ;-) – ScotchAndSoda

0

Możesz użyć dwóch sygnałów, aby zabić trwające wywołanie podprocesu, tj. Sygnał.SIGTERM i sygnał.SIGKILL; na przykład:

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) 
Powiązane problemy