Search code examples
pythonloopswhile-loopwaitpynput

Stop While Loop mid execution in python


I am trying to stop a while loop mid execution, if I reverse the value of 'runWhile' mid execution it simply waits until it's over.

Problem: I need it to stop immediately whenever I press f10 on the keyboard.

from pynput import keyboard
import threading
import datetime, time

def exec():
    while runWhile:
        print("There I go")
        time.sleep(3)
        print("I overtaken")
        time.sleep(3)
        print("You cant stop me until I finish")
        
def on_press(key):
    global runWhile # inform function to assign (`=`) to external/global `running` instead of creating local `running`

    if key == keyboard.Key.f5:
        runWhile = True
        t = threading.Thread(target=exec)
        t.start()
    if key == keyboard.Key.f10:
        # to stop loop in thread
        print("loading STOPPED", datetime.datetime.now()) #, end='\r')
        runWhile = False

    if key == keyboard.Key.f11:
        # stop listener
        print("listener TERMINATED", datetime.datetime.now()) #, end='\r')
        return False
        
        
#--- main ---
with keyboard.Listener(on_press=on_press) as listener:
    listener.join()

Im using pynput, docs here

based on @furas code


Solution

  • Here is a solution I made. I created my own delay function as follows:

    def delay(amount): #delay time in seconds
        for i in range(int(amount*60)):
            time.sleep(0.01)
            if runWhile == False:
                return True
                break
    

    You would replace your delay(3) with

    if delay(3):
        break
    

    This would wait 3 seconds, however if during that time, runWhile was false, it will break out of the loop. Your code would look like this:

    from pynput import keyboard
    import threading
    import datetime, time
    
    def delay(amount): #delay time in seconds
        for i in range(int(amount*60)):
          time.sleep(0.01)
          if runWhile == False:
            return True
            break
    
    def exec():
        while runWhile:
            print("There I go")
            if delay(3):
              break
            print("I overtaken")
            if delay(3):
              break
            print("You cant stop me until I finish")
            
    def on_press(key):
        global runWhile # inform function to assign (`=`) to external/global `running` instead of creating local `running`
    
        if key == keyboard.Key.f5:
            runWhile = True
            t = threading.Thread(target=exec)
            t.start()
        if key == keyboard.Key.f10:
            # to stop loop in thread
            print("loading STOPPED", datetime.datetime.now()) #, end='\r')
            runWhile = False
    
        if key == keyboard.Key.f11:
            # stop listener
            print("listener TERMINATED", datetime.datetime.now()) #, end='\r')
            return False
            
            
    #--- main ---
    with keyboard.Listener(on_press=on_press) as listener:
        listener.join()