Welcome, guest | Sign In | My Account | Store | Cart

This is a basic idiom I use on almost every thread I write.

Python, 55 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#!/usr/bin/env python
"""
testthread.py
An example of an idiom for controling threads

Doug Fort
http://www.dougfort.net
"""

import threading

class TestThread(threading.Thread):
    """
    A sample thread class
    """
        
    def __init__(self):
        """
        Constructor, setting initial variables
        """
        self._stopevent = threading.Event()
        self._sleepperiod = 1.0

        threading.Thread.__init__(self, name="TestThread")
        
    def run(self):
        """
        overload of threading.thread.run()
        main control loop
        """
        print "%s starts" % (self.getName(),)
        
        count = 0
        while not self._stopevent.isSet():
            count += 1
            print "loop %d" % (count,)
            self._stopevent.wait(self._sleepperiod)
        
        print "%s ends" % (self.getName(),)

    def join(self,timeout=None):
        """
        Stop the thread
        """
        self._stopevent.set()
        threading.Thread.join(self, timeout)

if __name__ == "__main__":
    testthread = TestThread()
    testthread.start()
    
    import time
    time.sleep(10.0)

    testthread.join()
    

It is based on using threading.Event to control the main thread loop. This gives the ability to pause the thread with Event.wait(), but to break out from join() (or wherever) without waiting for the timer to expire.

3 comments

Norbert Klamann 19 years, 5 months ago  # | flag

This one works on Win NT.

Noah Spurrier 14 years, 6 months ago  # | flag

Why do you call threading.Thread.join(self, timeout) instead of just calling self.join(timeout)? Why do you call threading.Thread.join(self, timeout) instead of just calling self.join(timeout) ? I use almost exactly the same idiom for trivial treads, but I have a generic thread looper that will run a loop on any given function:

#!/usr/bin/env python

import time
import threading

class thread_looper (threading.Thread):
    def __init__ (self, interval, function, args=[], kwargs={}):
        threading.Thread.__init__(self)
        self.interval = interval
        self.function = function
        self.args = args
        self.kwargs = kwargs
        self.finished = threading.Event()
    def stop (self):
        self.finished.set()
        self.join()
    def run (self):
        while not self.finished.isSet():
            self.finished.wait(self.interval)
            self.function(*self.args, **self.kwargs)

def my_function (a, b, c):
    print "meaningless arguments as an example:", a, b, c
    print time.asctime()

print "Calling my_function() in a thread every 1/10th of second for two seconds."
t = thread_looper (0.1, my_function, (1,0,-1))
t.start()
# The thread, t, runs while we are asleep.
time.sleep(2)
t.stop()
print "Done!"
harijay 10 years, 2 months ago  # | flag

I have a Thread that consumes work from a queue. I can get either test example to work but in my code I need to call self._Thread__stop() to have the thread terminate. Neither self.join() nor threading.Thread.join(self, timeout) stop the thread. Any ideas why?