Breaking a while loop from other method inside the same class in Python

I am wondering if I can run a while loop inside a method of a Python class that can be stopped from another method.

For example, something like this:

from time import sleep

class example():

    global recording

    def __init__(self):
        pass

    def start(self):
        global recording
        recording = True
        while recording:
            print(1)

    def stop(self):
        global recording
        recording = False
        print("SLEEEPINGGGGGGGGGGG")

a = example()
a.start()
sleep(0.5)
a.stop()

But, it does not work, the loop does not stop.

EDIT Since I do not want to create a Thread outside the class, I just tried this, but it doesn't work either.

from time import sleep
import threading

class example():

    def __init__(self):
        self.is_running = False

    def start(self):
        self.is_running = True
        self.loop_thread = threading.Thread(target=self.main_loop)

    def main_loop(self):
        while self.is_running:
            sleep(0.5)
            print(1)

    def stop(self):
        self.is_running = False
        print("SLEEEPINGGGGGGGGGGG")

a = example()
a.start()
sleep(3)
a.stop()

Upvotes: 4

Views: 1351

Answers (2)

jusx
jusx

Reputation: 1327

You have to start your thread after initiating it:

from time import sleep
import threading

class example():

    def __init__(self):
        self.is_running = False

    def start(self):
        self.is_running = True
        self.loop_thread = threading.Thread(target=self.main_loop)
        self.loop_thread.start() # <--- you forgot to start your thread

    def main_loop(self):
        while self.is_running:
            sleep(0.5)
            print(1)

    def stop(self):
        self.is_running = False
        print("SLEEEPINGGGGGGGGGGG")

a = example()
a.start()
sleep(3)
a.stop()

Upvotes: 1

Jean-Fran&#231;ois Fabre
Jean-Fran&#231;ois Fabre

Reputation: 140276

a.start() is an infinite loop. Since nothing runs at the same time, it just runs and never reaches the next statements.

You need to create a thread, like this

import time,threading

class example():

    def __init__(self):
        self.__recording = False

    def start(self):
        self.__recording = True
        while self.__recording:
            time.sleep(1)
            print(1)

    def stop(self):
        self.__recording = False

a = example()
t = threading.Thread(target=a.start)
t.start()
time.sleep(5)
a.stop()
t.join()

note that I have used a member variable instead of a global. When the start method sees that the variable is True, it quits the loop. job done.

That works because I'm using sleep(). If you're running a pure python CPU intensive job that won't work because of python GIL

As suggested in comments, you can go one step further and inherit from threading.Thread method instead:

import time,threading

class example(threading.Thread):

    def __init__(self):
        threading.Thread.__init__(self,target=self.run)

        self.__recording = False

    def run(self):
        self.__recording = True
        while self.__recording:
            time.sleep(1)
            print(1)

    def join(self):
        self.__recording = False
        threading.Thread.join(self)

a = example()
a.start()
time.sleep(5)
a.join()

Note that stop method is now replaced by join which signals the recording thread to stop then calls the parent join method. So when you join you stop the loop automatically first.

Upvotes: 7

Related Questions