0

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"
2
  • Just a warning, temp_c is being passed by value, so that will never change throughout the lifetime of the thread. Commented Nov 7, 2014 at 13:57
  • Yes; what I'm planning to do is to add as a thread the reading of temperature and as another one the control of fan and light to control the temperature. I've used a fixed value just to see if it was working. Commented Nov 7, 2014 at 14:07

2 Answers 2

1

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()
Sign up to request clarification or add additional context in comments.

6 Comments

I'm missing something. Do I need to add a except keyboard interupt into my functions to stop the threads?
@Yoann_R No, this should work. The main thread will die with the unhandled KeyboardInterrupt exception, and the threads will then in turn die as well because they were set to be daemon.
It's not working on my side. At first it displays:Traceback (most recent call last): File "C:\Users\test", line 50, in <module> t1.join() File "C:\Users", line 38, in join threading.Thread.join(self, 10) KeyboardInterrupt and after that it continues printing if I redo a CTRL c it just displays a KeyboardInterrupt
@Yoann_R Hmm odd, seems to be working for me. Just to be sure- this is what I'm running: pastebin.com/N6gYKgjQ
I've tried, it's the same result: not ending the threads. I'm running python 2.7.3 on windows. @dcexcal documentation from what I've understood; I have to look at lock.
|
1

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.