4
class My_Thread(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)

    def run(self):
        print "Starting " + self.name
        cmd = [ "bash", 'process.sh']
        p = subprocess.Popen(cmd,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.STDOUT)
        for line in iter(p.stdout.readline, b''):
            print ("-- " + line.rstrip())
        print "Exiting " + self.name

    def stop(self):
        print "Trying to stop thread "
        self.run = False

thr = My_Thread()
thr.start()
time.sleep(30)
thr.stop()
thr.join()

So i have thread like show above, actually work on windows and process.sh is bash script which run in cygwin and takes around 5 min to finish execution so its not a loop its some simulation proecess

i want to create stop() function in this class so that i can terminate script immediately when i want. after termination i am not expecting any useful result from process.sh script

please can u suggest any method, If possible please give little explanation too..

Ganesh Gore
  • 113
  • 1
  • 2
  • 8
  • Possible duplicate of [Is there any way to kill a Thread in Python?](http://stackoverflow.com/questions/323972/is-there-any-way-to-kill-a-thread-in-python) – Trevor Boyd Smith Oct 20 '16 at 13:38

2 Answers2

10

For your particular example, it's probably easiest to terminate the thread by terminating the subprocess it spawns using the Popen object's terminate() method...

class My_Thread(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self)
        self.process = None

    def run(self):
        print "Starting " + self.name
        cmd = [ "bash", 'process.sh']
        self.process = p = subprocess.Popen(cmd,
                     stdout=subprocess.PIPE,
                     stderr=subprocess.STDOUT)
        for line in iter(p.stdout.readline, b''):
            print ("-- " + line.rstrip())
        print "Exiting " + self.name

    def stop(self):
        print "Trying to stop thread "
        if self.process is not None:
            self.process.terminate()
            self.process = None

thr = My_Thread()
thr.start()
time.sleep(30)
thr.stop()
thr.join()

...causing a SIGTERM to be sent to bash, and the next call to p.stdout.readline() to raise an exception, which will terminate the thread.

Aya
  • 39,884
  • 6
  • 55
  • 55
  • But will it stop background running bash process or just avoids printing on console – Ganesh Gore Apr 28 '13 at 11:45
  • It will send `SIGTERM` to `bash` causing `bash` to terminate. – Aya Apr 28 '13 at 11:47
  • How can i call this stop() from other class which has my Tkinter GUI Button – Ganesh Gore Apr 28 '13 at 12:15
  • @GaneshGore You'd have to include the code, but it's probably best to open a new question, since it's a different issue. – Aya Apr 28 '13 at 12:19
  • @GaneshGore: [here's an example that shows: read output from a subprocess in a background thread, display the output in GUI, and *stop the subprocess using a Tkinter button*](https://gist.github.com/zed/42324397516310c86288) – jfs Apr 30 '13 at 20:23
  • @J.F. Sebastian Thank you for the sample code this is exactly what i want to do i haven't understood complete code yet but i will get back to you in any difficulties – Ganesh Gore May 19 '13 at 15:20
  • Funny thing: your **code works** but shows an error message saying "global name 'subprocess' is not defined". When I do `import subprocess` it gives no errors, but **doesn't work**. What? haha – George Apr 15 '16 at 19:22
6

Python threads are not easy to kill, you can use the multiprocessing module (http://docs.python.org/2/library/multiprocessing.html) which is almost the same and it has terminate() function for killing a processes.

Here is a little example, taken from the python docs.

>>> import multiprocessing, time, signal
>>> p = multiprocessing.Process(target=time.sleep, args=(1000,))
>>> print p, p.is_alive()
<Process(Process-1, initial)> False
>>> p.start()
>>> print p, p.is_alive()
<Process(Process-1, started)> True
>>> p.terminate()
>>> time.sleep(0.1)
>>> print p, p.is_alive()
<Process(Process-1, stopped[SIGTERM])> False
>>> p.exitcode == -signal.SIGTERM
True
nacholibre
  • 3,874
  • 3
  • 32
  • 35