Yoann_R
Yoann_R

Reputation: 99

Python exiting multiple threads

I'm trying to see how multi thread are working in order to use them in an automation project. I can run the thread but I cannot find a way to exit completely the two threads: the thread restart after each keyboard interupt. Is there a way to exit both thread with a keyboard interupt ?

import thread
from time import sleep

*parameters when starting
temp_c = 32
T_hot = 30
T_cold = 27
interval_temp = 2


def ctrl_fan(temp_c, T_hot,interval_temp):
    while True:
        if temp_c >= T_hot:
            print 'refreshing'
        else:
            print ' fan stopped'
        sleep(interval_temp)

    print 'shutting everything off'


def ctrl_light(temp_c, T_cold,interval_temp):
    while True:
        if temp_c <= T_cold:
            print 'warming'
        else:
            print 'light stopped'
        sleep(interval_temp)

    print 'shutting everything off'


try:
    thread.start_new_thread(ctrl_fan, (temp_c, T_hot,interval_temp, ) )

    sleep(1)

    thread.start_new_thread(ctrl_light, (temp_c, T_cold,interval_temp, ) )
except (KeyboardInterrupt, SystemExit):
    thread.exit()
    print "Error: unable to start thread"

Upvotes: 0

Views: 651

Answers (2)

dcexcal
dcexcal

Reputation: 195

The explanation is, again, in the documentation (https://docs.python.org/2/library/thread.html) :

Threads interact strangely with interrupts: the KeyboardInterrupt exception will be received by an arbitrary thread. (When the signal module is available, interrupts always go to the main thread.)

You'd certainly find answers in https://stackoverflow.com/, like :

Propagate system call interruptions in threads

Upvotes: 1

GP89
GP89

Reputation: 6730

Sure,

Firstly I'd recommend using the slightly higher level threading module instead of the thread module.

To start a thread with threading use the following

import threading
t = threading.Thread(target=ctrl_fan, args=(temp_c, T_hot, interval_temp))
t.start()

There's a few things you'll need to do to get the program to exit with a Ctrl-C interupt.

Firstly you will want to set the threads to be daemon, so that they allow the program to exit when the main thread exits (t.daemon = True)

You will also want the main thread to wait on the completion of the threads, you can use t.join() to do this. However this wont raise out a KeyboardInterrupt exception until the thread finishes, there is a work around for this though

while t.is_alive():
    t.join(1)

Providing a timeout value gets around this.

I'd be tempted to pull this together into a subclass, to get the behaviour you want

import threading

class CustomThread(threading.Thread):
    def __init__(self, *args, **kwargs):
        threading.Thread.__init__(self, *args, **kwargs)
        self.daemon = True

    def join(self, timeout=None):
        if timeout is None:
            while self.is_alive():
                threading.Thread.join(self, 10)
        else:
            return threading.Thread.join(self, timeout)

t1 = CustomThread(target=ctrl_fan, args=(temp_c, T_hot, interval_temp))
t1.start()

t2 = CustomThread(target=ctrl_light, args=(temp_c, T_cold, interval_temp))
t2.start()

t1.join()
t2.join()

Upvotes: 1

Related Questions