Search code examples
pythonpandasdatabasepyautogui

How to stop or pause pyautogui at any moment that I want?


I am building some macro program using pyautogui.

Unfortunately I am not able to stop for-loop so sometimes it takes too much time until for-loop end. Is there any way to stop the program at any moment I want? or I just wait until program end.

below is my code

CURRENT_DIR = os.getcwd()
list = os.path.join(CURRENT_DIR,'BOM_list.xlsx')
df = pd.read_excel(list)

for i in df['MLFB'].index:
    MLFB = df.loc[i, 'MLFB']
    print(MLFB)
    a = pyautogui.locateCenterOnScreen('a_material.png')
    print(a)
    pyautogui.moveTo(a)
    pyautogui.moveRel(350, 0)
    pyautogui.click()
    pyautogui.keyDown('ctrl')
    pyautogui.press('a')
    pyautogui.keyUp('ctrl')
    pyautogui.typewrite(MLFB)
    b = pyautogui.locateCenterOnScreen('b_execute.png')
    print(b)
    pyautogui.moveTo(b)
    pyautogui.click()
    time.sleep(2.5)
    pyautogui.keyDown('alt')
    pyautogui.press('y')
    pyautogui.press('t')
    pyautogui.press('a')
    pyautogui.press('i')
    pyautogui.keyUp('alt')
    time.sleep(2)
    pyautogui.press('down')
    pyautogui.typewrite(['enter'])
    time.sleep(2)

    c = pyautogui.locateCenterOnScreen('c_Directory.png')
    pyautogui.moveTo(c)
    pyautogui.moveRel(350, 0)
    pyautogui.click()
    pyautogui.keyDown('ctrl')
    pyautogui.press('a')
    pyautogui.keyUp('ctrl')
    pyautogui.typewrite(CURRENT_DIR)
    pyautogui.click()
    time.sleep(1.5)
    d = pyautogui.locateCenterOnScreen('d_Filename.png')
    pyautogui.moveTo(d)
    pyautogui.moveRel(350, 0)
    pyautogui.click()
    pyautogui.keyDown('ctrl')
    pyautogui.press('left')
    pyautogui.keyUp('ctrl')

    pyautogui.typewrite(MLFB)

    time.sleep(0.5)
    pyautogui.typewrite(['enter'])
    time.sleep(2)

    e = pyautogui.locateCenterOnScreen('e_go_back.png')
    pyautogui.moveTo(e)
    pyautogui.click()
    time.sleep(2)

Solution

  • PyAutoGUI has a built in failsafe to terminate the program at any time. Just move your mouse to the top left corner of your main monitor where your x, y values would be 0, 0.

    Typing print(pyautogui.FAILSAFE) should return True, telling us the failsafe is on. You could also disable it if it's getting in the way of your program by setting it to pyautogui.FAILSAFE = False

    Looking through your code, you could save some space by using hotkey() when you want to press more than one key at a time:

    pyautogui.keyDown('ctrl')
    pyautogui.press('a')
    pyautogui.keyUp('ctrl')
    

    Is the same as:

    pyautogui.hotkey('ctrl', 'a')
    

    You could also check out threading which allows you to run more than one process at a time.

    The following code will have an example main program running and when the Esc key is pressed, the main program will pause and the user is prompted if they want to continue or not.

    import time
    from threading import Thread
    from pynput import keyboard
    
    
    def exit_program():
        def on_press(key):
            if str(key) == 'Key.esc':
                main.status = 'pause'
                user_input = input('Program paused, would you like to continue? (y/n) ')
    
                while user_input != 'y' and user_input != 'n':
                    user_input = input('Incorrect input, try either "y" or "n" ')
    
                if user_input == 'y':
                    main.status = 'run'
                elif user_input == 'n':
                    main.status = 'exit'
                    exit()
    
        with keyboard.Listener(on_press=on_press) as listener:
            listener.join()
    
    
    def main():
        main.status = 'run'
    
        while True:
            print('running')
            time.sleep(1)
    
            while main.status == 'pause':
                time.sleep(1)
    
            if main.status == 'exit':
                print('Main program closing')
                break
    
    
    Thread(target=main).start()
    Thread(target=exit_program).start()