A better solution is to use the threading
module, which provides the Thread
class - an object-oriented interface to threads.
This way, we can easily join()
the three running threads (wait for them to finish).
Adapting your example:
import threading
import time
import random
keep_running = True
def runOften(threadName, sleepTime):
while keep_running:
time.sleep(sleepTime)
print "%s" %(threadName)
def runLessOften(threadName, sleepTime):
while keep_running:
time.sleep(sleepTime)
print "%s" %(threadName)
def runRandomly(threadName, sleepTime):
while keep_running:
time.sleep(sleepTime)
print "%s" %(threadName)
def main():
global keep_running
# Create the threads
threads = []
threads.append(threading.Thread(target=runOften, args=("Often Runs", 2)))
threads.append(threading.Thread(target=runLessOften, args=("Less Often Runs!", 2)))
threads.append(threading.Thread(target=runRandomly, args=("Fast and random", random.random())))
# Start the threads
for t in threads:
t.start()
# Wait for all of the threads to finish.
# Note: KeyboardInterrupt will not be raised inside of a call to join()
# with no timeout. So we set an arbitrarily large timeout, which
# (for whatever reason) allows KeyboardInterrupt to be raised.
while threads:
for t in list(threads): # Iterate over a copy
try:
t.join(1000) # Arbitrary timeout value
if not t.isAlive(): # If thread finished (join didn't time-out),
threads.remove(t) # We'll no longer join() on it
except KeyboardInterrupt: # If we get a Ctrl+C,
keep_running = False # Set global flag, telling threads to stop looping
if __name__ == '__main__':
main()
Why is this better than (even though it's aesthetically inferior to) while True: pass
? Because that will make the CPU busy-wait for the Ctrl+C, robbing valuable execution time from the other threads. This solution will instead allow the other threads to run, only waking up when Ctrl+C is pressed.
Other questions on handling Ctrl+C with threads:
I should also point out that runRandomly
doesn't do what its name implies; instead, it will always sleep the same amount of time every iteration. That amount is randomly decided once when the program starts.