I\'m launching a subprocess with the following command:
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
However, when I try t
Although it is an old question, it has a high google rank. so I decided to post an answer with the new method someone can use in python 3 to manage this easily and with confidence. as of python 3.5 you there is a new method added to subprocess
package called run().
As the documentation says:
It is the recommended approach to invoking sub processes for all use cases it can handle. For more advanced use cases, the underlying
Popen
interface can be used directly.
The subprocess.run():
Runs a command described by args. Wait for the command to complete, then return a
CompletedProcess
instance.
for example one can run this snippet within a python console:
>>> subprocess.run(["ls", "-l"]) # doesn't capture output
CompletedProcess(args=['ls', '-l'], returncode=0)
P.S. In case of the OP's specific question, I wasn't able to reproduce his problem. commands I run with popen() are terminating properly.
None of this answers worked for me so Im leaving the code that did work. In my case even after killing the process with .kill()
and getting a .poll()
return code the process didn't terminate.
Following the subprocess.Popen
documentation:
"...in order to cleanup properly a well-behaved application should kill the child process and finish communication..."
proc = subprocess.Popen(...)
try:
outs, errs = proc.communicate(timeout=15)
except TimeoutExpired:
proc.kill()
outs, errs = proc.communicate()
In my case I was missing the proc.communicate()
after calling proc.kill()
. This cleans the process stdin, stdout ... and does terminate the process.
Send the signal to all the processes in group
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)
As Sai said, the shell is the child, so signals are intercepted by it -- best way I've found is to use shell=False and use shlex to split the command line:
if isinstance(command, unicode):
cmd = command.encode('utf8')
args = shlex.split(cmd)
p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
Then p.kill() and p.terminate() should work how you expect.
I know this is an old question but this may help someone looking for a different method. This is what I use on windows to kill processes that I've called.
si = subprocess.STARTUPINFO()
si.dwFlags |= subprocess.STARTF_USESHOWWINDOW
subprocess.call(["taskkill", "/IM", "robocopy.exe", "/T", "/F"], startupinfo=si)
/IM is the image name, you can also do /PID if you want. /T kills the process as well as the child processes. /F force terminates it. si, as I have it set, is how you do this without showing a CMD window. This code is used in python 3.
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.