In my application I have two threads. Main one and "thread". therad generates some data and stores it in a python list. The main thread periodically copies the content of the list generated by "thread". Both threads have an infinite while loop. My goal is stopping both threads when I press any key+enter. To achieve this goal, the program must wait for a keyboard input while the threads are running. I thought I need another thread (lets say manager) which is only waiting for a keyboard input during execution. Here is what I tried first:
class managerThread(threading.Thread):
is_running = True
def __init__(self):
threading.Thread.__init__(self)
signal.signal(signal.SIGINT, self.kill_all)
signal.signal(signal.SIGTERM, self.kill_all)
def run(self):
input("Press any key+enter to stop: ")
self.is_running = False
def kill_all(self,signum, frame):
print("Process ended with keyboard interrupt")
self.is_running = False
sys.exit(-1)
class thread(threading.Thread):
mgr = managerThread()
mgr.start()
def __init__(self):
threading.Thread.__init__(self)
def run(self):
while (self.mgr.is_running):
print("this is acquiring data")
sleep(2.5)
self.mgr.join()
print("manager stopped")
if __name__ == "__main__":
thread = thread()
thread.start()
while (thread.mgr.is_running):
print("this is copying data")
sleep(3)
thread.join()
print("thread is stopped")
sys.exit(0)
Above code is doing exactly what I want to do. Bu this does not seem correct. The manager manages all the others but it is created in one of the slave threads. Another problem is one may try to create multiple managers in different threads. This is something must be strictly avoided. Then I thought the manager must be inherited by the managed classes. Here is what I tried:
class managerThread(threading.Thread):
is_running = True
def __init__(self):
threading.Thread.__init__(self)
signal.signal(signal.SIGINT, self.kill_all)
signal.signal(signal.SIGTERM, self.kill_all)
self.start()
def run(self):
input("Press any key+enter to stop: ")
self.is_running = False
def kill_all(self,signum, frame):
print("Process ended with keyboard interrupt")
self.is_running = False
sys.exit(-1)
class thread(managerThread):
def __init__(self):
super().__init__()
threading.Thread.__init__(self)
def run(self):
while (self.is_running):
print("this is acquiring data")
sleep(2.5)
print("manager stopped")
if __name__ == "__main__":
thread = thread()
thread.start()
while (thread.is_running):
print("this is copying data")
sleep(3)
thread.join()
print("thread is stopped")
sys.exit(0)
As seen in the second code the major part is the same. I tried to make thread
as a child of managerThread
. However this is not working. The manager never executes "run" method. So I cannot stop the other threads. Another crucial problem is I do not how to stop super()
with join()
. I am sure I am doing a mistake about class inheritance but I could not resolve the problem since I do not have too much experience with OOP and threads doubled my confusion.
Note: I do not care about synchronization of the threads.
My questions are:
- Is creating a manager thread correct to safely stop the slave threads? If not, what is the proper way?
- Why the second code is not working? What do I have to modify to get it work?
- Why the parent class is initializing but it is never running "run" method?
- I believe that the parent class is never starting but how can I stop it in the second code if it is actually starting?
Thank you.
Even I did not want to use a global variable to stop safely all the threads I could not find a solution without a global running flag. I also tried to pass a mutable variable to the manager thread but I was unsuccessful. Here is a working sketch that explains how I solved my problem. I hope this helps someone else. Meanwhile, I would be happy if someone propose a better solution :).
Note: I did not debug it.
import sys
import threading, queue
import signal
from time import sleep
import numpy as np
global_running = False
class managerThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
signal.signal(signal.SIGINT, self.kill_all)
signal.signal(signal.SIGTERM, self.kill_all)
def run(self):
global is_running
is_running = True
input("Press any key+enter to stop: ")
is_running = False
print("manager finished")
def kill_all(self,signum, frame):
global is_running
is_running = False
print("Process ended with keyboard interrupt")
sys.exit(-1)
class thread(threading.Thread):
__mgr = managerThread()
__mgr.start()
running = True
def __init__(self):
threading.Thread.__init__(self)
self.myvar = 0
self.queue = queue.Queue()
def currentVar(self):
var = np.empty(1)
while (var.size<=1):
var = self.queue.get()
self.queue.task_done()
return var
def run(self):
global is_running
while (is_running):
print("this is acquiring data")
sleep(2.5)
self.myvar = np.empty(5)
self.queue.put(self.myvar)
self.running = False
self.__mgr.join()
print("manager stopped")
if __name__ == "__main__":
thread = thread()
thread.start()
while (thread.running):
# var = thread.queue.get()
var = thread.currentVar()
print ("value is: ", var)
# thread.queue.task_done()
thread.join()
print("thread is stopped")
sys.exit(0)