How to terminate a python subprocess launched with shell=True
Hire the world's top talent on demand or became one of them at Toptal: https://topt.al/25cXVn
and get $2,000 discount on your first invoice
--------------------------------------------------
Music by Eric Matyas
https://www.soundimage.org
Track title: Switch On Looping
--
Chapters
00:00 How To Terminate A Python Subprocess Launched With Shell=True
00:35 Answer 1 Score 21
00:58 Accepted Answer Score 554
01:36 Answer 3 Score 142
02:05 Answer 4 Score 43
02:20 Thank you
--
Full question
https://stackoverflow.com/questions/4789...
--
Content licensed under CC BY-SA
https://meta.stackexchange.com/help/lice...
--
Tags
#python #linux #subprocess #killprocess
#avk47
ACCEPTED ANSWER
Score 554
Use a process group so as to enable sending a signal to all the process in the groups. For that, you should attach a session id to the parent process of the spawned/child processes, which is a shell in your case. This will make it the group leader of the processes. So now, when a signal is sent to the process group leader, it's transmitted to all of the child processes of this group.
Here's the 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
ANSWER 2
Score 142
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
p.kill()
p.kill() ends up killing the shell process and cmd is still running.
I found a convenient fix this by:
p = subprocess.Popen("exec " + cmd, stdout=subprocess.PIPE, shell=True)
This will cause cmd to inherit the shell process, instead of having the shell launch a child process, which does not get killed.  p.pid will be the id of your cmd process then.
p.kill() should work.
I don't know what effect this will have on your pipe though.
ANSWER 3
Score 43
I could do it using
from subprocess import Popen
process = Popen(command, shell=True)
Popen("TASKKILL /F /PID {pid} /T".format(pid=process.pid))
it killed the cmd.exe and the program that i gave the command for.
(On Windows)
ANSWER 4
Score 21
When shell=True the shell is the child process, and the commands are its children. So any SIGTERM or SIGKILL will kill the shell but not its child processes, and I don't remember a good way to do it.
 The best way I can think of is to use shell=False, otherwise when you kill the parent shell process, it will leave a defunct shell process.