Jack Daniel
Jack Daniel

Reputation: 2611

Stop while loop with class level variables

I am building a monitoring system where I once start the application, it will continuously monitor the changes and output the results to the database. For this, I used a while loop for continuous monitoring for the repetitive tasks. Here, I am using a class-level variable as 'True' for the condition in while loop. Here I am stuck with how can I change the flag to 'False' when the application is running in while loop.

Sample code looks as follow:

class Monitor:
def __init__(self):
    self.monitor=True

def start(self):
    i=0
    while(self.monitor):
        i+=1

I am running the below lines to run the code in the command line:

>>> from StartStopMontoring import Monitor
>>> m=Monitor()
>>> m.start()

^CTraceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Volumes/DATA/Innominds/WorkSpace/Python/StartStopMontoring.py", line 7, in start
    while(self.monitor):
KeyboardInterrupt
>>> 

Second-line creates the object and the third line calls the function, then I am unable to set the flag to false since it is in while loop with always true condition is met. (I had to interrupt the command line to stop the application).

Precisely, How can I set a class level flag to false when while loop is running?

Note: This flag changes happen from external input like user want to stop the system but not when conditions met internally within the loop.

Upvotes: 1

Views: 131

Answers (2)

Vishal
Vishal

Reputation: 3296

With below code you can either temporarily halt the monitoring, or quit the monitoring completely.

import threading
import time

class Monitor(threading.Thread):
    def __init__(self):
        self.b_quit = False
        self.monitor = True
        self.event = threading.Event()  # Whenever this event is set, monitoring should happen
        self.event.set()  # By default turn on monitoring
        threading.Thread.__init__(self)

    def run(self):
        i = 0
        while self.monitor:
            eventSet = self.event.wait()
            if not self.monitor or self.b_quit:
                break

            print("---- Thread is active: {}".format(i), end='\r')
            i += 1

    def begin(self):
        self.event.set()

    def halt(self):
        self.event.clear()

    def quit(self):
        self.event.set()
        self.b_quit = True


obj = Monitor()
obj.start() # Launches a separate thread which can be controlled, based upon calls to begin, halt, and quit
time.sleep(1)
print("Trigger halt from main thread")
obj.halt()  # Only paused the monitoring
time.sleep(1)
print("Trigger resume from main thread")
obj.begin()  # Resumes the monitoring
time.sleep(1)
print("Trigger quit from main thread")
obj.quit()   # Exits the thread completely

Upvotes: 1

Akami
Akami

Reputation: 189

Launch the loop in a different thread so that you don't lose the control of your program.

import threading
class Monitor:

    (....)

    def start(self):
        threading.Thread(target=self.run).start()

    def run(self):
        i=0
        while self.monitor:
             i += 1

Upvotes: 1

Related Questions