Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How terminate Python thread without checking flag continuously

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..

like image 452
Ganesh Gore Avatar asked Dec 04 '22 11:12

Ganesh Gore


2 Answers

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.

like image 122
Aya Avatar answered Jan 28 '23 09:01

Aya


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
like image 32
nacholibre Avatar answered Jan 28 '23 11:01

nacholibre