I've just discovered the threading.Event class, which has the methods set() and is_set() to communicate between threads. There is also a wait(timeout=None) method, which blocks until the flag is set.
import os
import sys
import threading
import time
# this is where the real work is done
def function(duration, e):
time.sleep(duration)
# signal to the other thread that we're done
e.set()
# the thread associated with this function prints out a status message
def status(e):
# wait for the other thread to tell us when it's done
print('waiting', end='')
sys.stdout.flush()
while not e.is_set():
time.sleep(1)
print('.', end='')
sys.stdout.flush()
print('\r', end='')
print('done'.ljust(100))
def main():
duration = int(sys.argv[1])
# the event object has a flag that may be monitored by other threads for synchronisation
e = threading.Event()
t1 = threading.Thread(target=function, args=(duration, e,))
t2 = threading.Thread(target=status, args=(e,))
t2.start() # start the status thread first
t1.start()
t1.join() # join the work thread first
t2.join() # finally, join the status thread
return os.EX_OK
if __name__ == "__main__":
sys.exit(main())