16

I'm launching a program with subprocess on Python.

In some cases the program may freeze. This is out of my control. The only thing I can do from the command line it is launched from is CtrlEsc which kills the program quickly.

Is there any way to emulate this with subprocess? I am using subprocess.Popen(cmd, shell=True) to launch the program.

freginold
  • 3,946
  • 3
  • 13
  • 28
Thomas O
  • 6,026
  • 12
  • 42
  • 60

6 Answers6

25

Well, there are a couple of methods on the object returned by subprocess.Popen() which may be of use: Popen.terminate() and Popen.kill(), which send a SIGTERM and SIGKILL respectively.

For example...

import subprocess
import time

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

...would terminate the process after five seconds.

Or you can use os.kill() to send other signals, like SIGINT to simulate CTRL-C, with...

import subprocess
import time
import os
import signal

process = subprocess.Popen(cmd, shell=True)
time.sleep(5)
os.kill(process.pid, signal.SIGINT)
Aya
  • 39,884
  • 6
  • 55
  • 55
  • 4
    On Windows `kill = terminate` and signals do not work the same way. – jfs Jun 01 '13 at 00:04
  • 1
    This answer is missing a call to `process.wait()` — https://stackoverflow.com/questions/55052055/why-do-i-get-subprocess-resource-warnings-despite-the-process-being-dead – Clément Jul 12 '21 at 03:24
19
p = subprocess.Popen("echo 'foo' && sleep 60 && echo 'bar'", shell=True)
p.kill()

Check out the docs on the subprocess module for more info: http://docs.python.org/2/library/subprocess.html

butch
  • 2,178
  • 1
  • 17
  • 21
0

Your question is not too clear, but If I assume that you are about to launch a process wich goes to zombie and you want to be able to control that in some state of your script. If this in the case, I propose you the following:

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

This in not really recommanded to pass through the shell. I would suggest you ti use shell=False, this way you risk less an 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"
ScotchAndSoda
  • 3,811
  • 4
  • 34
  • 38
  • - p.pid is a property of Popen instances, not a method - When exactly is the OSError being raised? Even for simple Popen calls ( subprocess.Popen("ls", shell=False)) I can't seem to get to the except statement. – bergercookie Nov 25 '16 at 12:54
  • it's right, pid is a property, it should be a typing error. For the OSError the exception is raised at the os.kill(pid, 0) step if the pid does not exist anymore - p.terminate() has terminated the pid with success ;-) – ScotchAndSoda Dec 07 '16 at 17:38
  • is both `os.kill` and `p.kill` needed? Isnt one enough? – leoOrion May 25 '20 at 04:18
0

You can use two signals to kill a running subprocess call i.e., signal.SIGTERM and signal.SIGKILL; for example

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)
Asif Hasnain
  • 179
  • 1
  • 1
  • Instead of `sleep(2)` + `poll` you can use `wait(2)` with a timeout, which won't waste two seconds if the process exits quickly. Additionally, you can use `process.terminate` and `process.kill` instead of `os.killpg`. – Clément Jul 12 '21 at 03:26
0

Following command worked for me

os.system("pkill -TERM -P %s"%process.pid)
Lava Sangeetham
  • 2,943
  • 4
  • 38
  • 54
-1

Try wrapping your subprocess.Popen call in a try except block. Depending on why your process is hanging, you may be able to cleanly exit. Here is a list of exceptions you can check for: Python 3 - Exceptions Handling

Micheal Bee
  • 550
  • 5
  • 11