I am trying to get started with multithreading in Python. I have multiple threads that acquire a lock, perform an operation, release the lock, and output the result to a csv file. The threads should be terminated in case the main thread finishes (e.g. through pressing Ctrl+C). How is this done?
I thought making the threads daemons should do the job, because "the entire Python program exits when only daemon threads are left" (official Python documentation). This is not sufficient. According to python: how to terminate a thread when main program ends, I then tried catching a KeyboardInterrupt and then terminating the threads manually. Also this is not working, it seems that the KeyboardInterrupt is not catched correctly.
It makes me think, there is something about multithreading in Python that I misunderstood... Find attached my code:
import random
import csv
import sys
from datetime import datetime
import threading
lock = threading.Lock()
def observer(obs):
print("In " + str(obs))
sys.stdout.flush()
with open("data/test_" + str(obs) + ".csv", 'a', newline='') as csvfile:
while True:
datenow = datetime.today()
lock.acquire()
print(str(obs) + "acquired")
sum = 0
for i in range(10000):
sum = sum + random.random()
print(str(obs) + "released")
sys.stdout.flush()
lock.release()
writer = csv.writer(csvfile, delimiter=',', quoting=csv.QUOTE_ALL)
writer.writerow([datenow.isoformat(), sum/10000])
#print(str(obs) + ": " + datenow.isoformat() + " " + str(sum/1000))
sys.stdout.flush()
if __name__ == "__main__":
observe = [1, 2, 3, 4]
processes = []
for obs in observe:
process = threading.Thread(target=observer, args=(obs,), daemon=True)
processes.append(process)
print("Start processes")
for p in processes:
p.start()
print("Started")
try:
for p in processes:
p.join()
except KeyboardInterrupt:
for p in processes:
p.terminate()
print("Keyboard interrupt")
print("Finished")
Thanks!