I have a complete "working" python code which is supposed to contain two threads which run simultaneously, which populate some lists in a dict, and when the user presses CRTL-C these two threads should be stopped and some output from both threads should be written to a file:
import sys
import time
import threading
import signal
from functools import partial
messages = {}
lock = threading.Lock()
class Handler:
def __init__(self, port):
self.port = port
def run(self):
while True:
time.sleep(1)
with lock:
messages[self.port].append(time.time())
def signal_handler(filename, sig, frame):
with lock:
with open(filename, "w") as fileout:
json.dump(messages, fileout)
sys.exit(0)
output = "test.out"
signal.signal(signal.SIGINT, partial(signal_handler, output))
for port in [1,2]:
messages[port] = []
handler = Handler(port)
print("debug1")
t = threading.Thread(target=handler.run())
print("debug2")
t.daemon = True
t.start()
threads.append(t)
# Keep the main thread running, waiting for CTRL-C
try:
while True:
pass
except KeyboardInterrupt:
signal_handler(output, signal.SIGINT, None)
However, this code blocks execution after the first debug1
has been printed. How to "unblock" this line so the two threads are started until the user presses CRTL-C (and the output is saved to a file)?
...The above code is just a template of a more complicated code that actually does something useful...
Apart from various typos (forgotten import json
and threads=[]
) the main problem is in t = threading.Thread(target=handler.run())
.
The target
parameter is expected to be a function object, not the result of the call of that function. Here this code immediately calls the never ending function to assign its never coming result to t
, actually blocking the main program.
The solution is just to remove the parens:
t = threading.Thread(target=handler.run)