Startec
Startec

Reputation: 13246

How to kill a subprocess started in a thread?

I am trying to run the Robocopy command (but I am curious about any subprocess) from Python in windows. The code is pretty simple and works well. It is:

def copy():
    with Popen(['Robocopy', media_path, destination_path, '/E', '/mir', '/TEE', '/log+:' + log_path], stdout=PIPE, bufsize=1, universal_newlines=True) as Robocopy:
        Robocopy.wait()
        returncode = Robocopy.returncode

Additionally I am running it in a separate thread with the following:

threading.Thread(target=copy, args=(media_path, destination_path, log_path,), daemon=True)

However, there are certain instances where I want to stop the robocopy (akin to closing the CMD window if it was run from the command line)

Is there a good way to do this in Python?

Upvotes: 0

Views: 1242

Answers (2)

jfs
jfs

Reputation: 414835

If the process doesn't start other processes then process.kill() should work:

import subprocess

class InterruptableProcess:
     def __init__(self, *args):
         self._process = subprocess.Popen(args)

     def interrupt(self):
         self._process.kill()

I don't see why would you need it on Windows but you could run Thread(target=self._process.wait, daemon=True).start() if you'd like.

If there is a possibility that the process may start other processes in turn then you might need a Job object to kill all the descendant processes. It seems killableprocess.py which is suggested by @rrauenza uses this approach (I haven't tested it). See Python: how to kill child process(es) when parent dies?.

Upvotes: 1

rrauenza
rrauenza

Reputation: 6993

We fought with reliably killing subprocesses on Windows for a while and eventually came across this:

https://github.com/andreisavu/python-process/blob/master/killableprocess.py

It implements a kill() method for killing your subprocess. We've had really good results with it.

You will need to somehow pass the process object out of the thread and call kill() from another thread, or poll in your thread with wait() using a timeout while monitoring some kind of global-ish flag.

Upvotes: 1

Related Questions