Home > Software design >  Break out of a for loop nested in a while loop when while loop's condition becomes False
Break out of a for loop nested in a while loop when while loop's condition becomes False

Time:03-24

I have a while loop that iterates for 8 seconds, and inside it is a for loop which iterates 4 times, each time executing some pyautogui press functions. However, when my loop breaks, the for loop within continues until completion. Code:

import time
import pyautogui

timeout = time.time()   8


while time.time() < timeout:
    for i in range(4):
        pyautogui.press("1")
        pyautogui.press("1")
        pyautogui.press("1")
        pyautogui.press("1")
        pyautogui.press("1")
        pyautogui.press("1")
        pyautogui.press("1")
        pyautogui.press("1")
        pyautogui.press("1")
        pyautogui.press("1")
        pyautogui.press("4")
        pyautogui.press("enter")
print(f"{time.time() - timeout } seconds more than while loop execute time")

Print statement output:

2.4774444103240967 seconds more than while loop execute time

So, how can I get my for loop to end with my while loop? I checked around on stack overflow but found nothing.

(used pyautogui.press("") cause I got my error using them and they execute slower than print statements (can see the time difference better))

CodePudding user response:

Well, your description doesn't reflect reality. The "for" loop certainly will end with the "while" loop, but you can't interrupt the "for" loop in the middle. If you want to stop in mid-keystroke, then you'll need to check the time at every keystroke:

import time
import pyautogui

timeout = time.time()   8
msg = "11111111114*" * 4

for c in msg:
    if time.time() >= timeout:
        break
    if c == '*':
        c = 'enter'
    pyautogui.press(c)
print(f"{time.time() - timeout } seconds more than while loop execute time")

Alternatively:

import time
import pyautogui

timeout = time.time()   8
msg = (list("11111111114") ['enter']) * 4

while time.time() < timeout:
    if msg:
        pyautogui.press(msg.pop(0))
    else:
        time.sleep(0.1)

print(f"{time.time() - timeout } seconds more than while loop execute time")

CodePudding user response:

You can replace the body of the while loop with a call to next on an appropriately defined generator. In some sense, this is a primitive implementation of a thread; execution of the generator is interleaved with the repeated evaluations of the timeout condition. (In practice, this may only be useful as an example of how threading works.)

def my_generator():
    for i in range(4):
        yield pyautogui.press("1")
        yield pyautogui.press("1")
        yield pyautogui.press("1")
        yield pyautogui.press("1")
        yield pyautogui.press("1")
        yield pyautogui.press("1")
        yield pyautogui.press("1")
        yield pyautogui.press("1")
        yield pyautogui.press("1")
        yield pyautogui.press("1")
        yield pyautogui.press("4")
        yield pyautogui.press("enter") 
    
foo = my_generator()

while time.time() < timeout:
    next(foo)
  • Related