Python Forum
How to break a loop in this case?
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to break a loop in this case?
#1
I got this to work, but when I press s to stop the script, it will keep running the marketloop() function till end before stopping. My question is that how do I make the function stop instantly too? I tried adding break in stop buffing function but returned an expected 'break' outside loop error.

import pyautogui as pg
import time
import keyboard
import random
import win32api, win32con
import threading
from pynput.mouse import Button, Controller
from pynput.keyboard import Listener, KeyCode

start_stop_key = KeyCode(char='s')
exit_key = KeyCode(char='q')

def marketloop():
      #this has code that clicks through lots of things


class BuffItems(threading.Thread):
    def __init__(self):
        super(BuffItems, self).__init__()
        self.running = False
        self.program_running = True

    def start_buffing(self):
        self.running = True

    def stop_buffing(self):
        self.running = False
        

    def exit(self):
        self.stop_buffing()
        self.program_running = False

    def run(self):
        while self.program_running:
            while self.running:
                marketloop()


                
buff_thread = BuffItems()
buff_thread.start()
                

def on_press(key):
    if key == start_stop_key:
        if buff_thread.running:
            buff_thread.stop_buffing()
        else:
            buff_thread.start_buffing()
    elif key == exit_key:
        buff_thread.exit()
        listener.stop()

with Listener(on_press=on_press) as listener:
    listener.join()
Reply
#2
Hi,

Im not a 100% certain but hopefully this will help.

If you want the program to stop when you press the key "S". Then maybe something within the loop like.

if key_press = s:
   break
If you have that in the loop then it will check everytime the loop is run. As i said not 100% it will work but hopefully it helps.
"Only Boring People Get Bored"
Reply
#3
(Sep-24-2020, 05:19 AM)finndude Wrote: If you have that in the loop then it will check everytime the loop is run.

Thanks, I cut lot of it out but basically the marketloop looks like this, and when I added the code you provided on top, it still says the 'break' out of loop - error.

def marketloop():
    if key_press == s:
        break   

    offers = pg.locateCenterOnScreen('offers.PNG', region=(0,0,1919,1079), grayscale=False, confidence=0.80)
    time.sleep(0.5)
    pg.click(offers.x, offers.y)
    time.sleep(0.5)

    search = pg.locateCenterOnScreen('search.PNG', region=(0,0,1919,1079), grayscale=False, confidence=0.80)
    time.sleep(0.5)
    pg.click(search.x, search.y)
    time.sleep(0.5)

    settings = pg.locateCenterOnScreen('settings.PNG', region=(0,0,1919,1079), grayscale=False, confidence=0.80)
    time.sleep(0.5)
    pg.click(settings.x, settings.y)
    time.sleep(0.5)

    #lots of the same cut out
Reply
#4
What you show isn't a loop, it's a function. If you want to exit the function early, you use return.

Instead you need to find the (likely) loop where this function is called. You probably will be able to break or otherwise exit out of that loop.
Reply
#5
(Sep-24-2020, 06:45 AM)bowlofred Wrote: What you show isn't a loop, it's a function.

Ah, I kind of fooled myself by naming the function as loop, I guess :D Is there way to call that return outside of the function?
Reply
#6
I changed your code a bit.
Does marketloop require access to key events?
If it's the case, code needs to be changed. Again.

import pyautogui as pg
import time
import keyboard
import random
import win32api, win32con
import threading
from pynput.mouse import Button, Controller
from pynput.keyboard import Listener, KeyCode


class BuffItems(threading.Thread):
    def __init__(self):
        super().__init__()
        self.running = False
        self.pause = False
 
    def start(self):
        """
        Duplicates the start method of threading.Thread
        """
        if not self.running:
            self.running = True
            super().start()

    def stop(self):
        self.running = False

    def pause_toggle(self):
        self.pause = not self.pause
 
    def run(self):
        while self.running:
            time.sleep(0.5) # to reduce speed
            if not self.pause:
                marketloop()


class KeyboardControl:
    start_stop_key = KeyCode(char='s')
    exit_key = KeyCode(char='q')

    def __init__(self):
        self.listener = Listener(on_press=self.on_press)
        self.listener.start()
        self.buff_thread = BuffItems()
        self.buff_thread.start()

    def __enter__(self):
        return self

    def __exit__(self, *args):
        self.buff_thread.stop()
        self.listener.stop()
        
    def on_press(self, key):
        if key == self.start_stop_key and self.buff_thread.running:
            self.buff_thread.pause_toggle()
        elif key == self.exit_key and self.buff_thread.running:
            self.buff_thread.stop()
            self.listener.stop()

    def join(self):
        while self.buff_thread.running:
            time.sleep(0.1)


def marketloop():
    print(time.time())


def main():
    try:
        with KeyboardControl() as control:
            control.join()
    except KeyboardInterrupt:
        print("\nReceived SIGINT. Exitting programm.")


if __name__ == "__main__":
    main()
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#7
Thanks, but I don't understand the changes :D I'm learning python, by jumping feet first and I barely managed to get the code work in the first place.. It would probably be too much to ask to explain the changes you made, so I won't.. Instead I'll keep hacking at it, I'll return to your post when I have learned a bit more!
Reply
#8
For beginners classes are not the best choice until object-oriented programming is understood.
Do you want a kind of interruption somewhere in the marketloop?
Also mine implementation has no method to stop marketloop doing its work when it was called.
Actually it would just print the time and your example has some time.sleep and stuff from pyautogui inside.
All this is executed, until the function is left and then the loop is calling again the marketplace function, if it was not stopped.
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#9
Yes, I'm just looking for a way to stop a longer function (within a loop) with a press of a key. In my example the function is repeated as long as the program is running and as long as I don't press 's' key to stop it, but even then the function will run till completion before stopping the repetition.

Just to give an idea what the marketloop() is currently set to do, is that it will click though series of buttons to navigate in a game screen, so it will take a moment to finish with all the small sleeps in between the clicks. I want that to stop instantly when I press the button and not wait until it finish.
Reply
#10
Unless you create some sort of multi-threaded app (which is not easy), there's no way to stop a function from the outside. The outside program is just waiting for the function to return.

Some options:
That marketloop() function is doing a lot of repetitive things. A loop would be good for it. If you had the data in a nice map, you could loop over them, and then check for the keypress (and exit) if you see it.

files = {
    "offers": "offers.PNG"
    "search": "search.PNG"
    "settings": "settings.PNG"
}

def marketloop():
    for region, filename in files.each():
        data = pg.locateCenterOnScreen(filename, region=(0,0,1919,1079), grayscale=False, confidence=0.80)
        time.sleep(0.5)
        pg.click(data.x, data.y)
        time.sleep(0.5)
        if check_keypress() == pressed: #however you do this...
            return # Exits the function immediately.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Code won't break While loop or go back to the input? MrKnd94 2 947 Oct-26-2022, 10:10 AM
Last Post: Larz60+
  How to break out of a for loop on button press? philipbergwerf 6 1,740 Oct-06-2022, 03:12 PM
Last Post: philipbergwerf
  break out of for loop? User3000 3 1,444 May-17-2022, 10:18 AM
Last Post: User3000
  Asyncio: Queue consumer gets out of while loop without break. Where exactly and how? saavedra29 2 2,682 Feb-07-2022, 07:24 PM
Last Post: saavedra29
  Switch case or match case? Frankduc 9 4,499 Jan-20-2022, 01:56 PM
Last Post: Frankduc
  tkinter control break a while loop samtal 0 2,388 Apr-29-2021, 08:26 AM
Last Post: samtal
  Cannot 'break' from a "for" loop in a right place tester_V 9 3,986 Feb-17-2021, 01:03 AM
Last Post: tester_V
  how to break the loop? bntayfur 8 3,063 Jun-07-2020, 11:07 PM
Last Post: bntayfur
  break for loop Agusben 1 1,911 Apr-01-2020, 05:07 PM
Last Post: Larz60+
  Help For AutoGui Loop break ahmetnwpal 0 1,963 Mar-11-2020, 01:14 PM
Last Post: ahmetnwpal

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020