Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to jump out of a dead loop automatically in Python?

Tags:

python

I have a "do..., until..." structure in Python as follows:

while True:
    if foo() == bar():
        break

It works fine (jumps out in the end) in most of the cases. However, in some of the cases where the condition is never met, it will get stuck there.

Figuring out what are these cases is kind of difficult, since it is essentially a random process behind. So I wish to set a "timeout" thing for the while loop.

Say, if the loop has been running for 1s, but still not yet stops, I wish the loop to terminate itself.

How may I do this?


Update: Here is the actual code:

while True:
    possibleJunctions = junctionReachability[junctions.index(currentJunction)]
    nextJunction = random.choice(filter(lambda (jx, jy): (jx - currentJunction[0]) * (endJunction[0] - currentJunction[0]) > 0 or (jy - currentJunction[1]) * (endJunction[1] - currentJunction[1]) > 0, possibleJunctions) or possibleJunctions)
    if previousJunction != nextJunction: # never go back        
        junctionSequence.append(nextJunction)
        previousJunction = currentJunction
        currentJunction = nextJunction
    if currentJunction == endJunction:
        break
like image 427
Sibbs Gambling Avatar asked Dec 15 '22 06:12

Sibbs Gambling


2 Answers

import time

loop_start = time.time()
while time.time() - loop_start <= 1:
    if foo() == bar():
        break
like image 152
Dan Doe Avatar answered Dec 29 '22 23:12

Dan Doe


EDIT

Dan Doe's solution is simplest and best if your code is synchronous (just runs in a single thread) and you know that the foo and bar functions always terminate within some period of time.

If you have asynchronous code (like a GUI), or if the foo and bar functions you use to test for termination conditions can themselves take too long to complete, then read on.

Run the loop inside a separate thread/process. Run a timer in another process. Once the timer expires, set a flag that would cause the loop to terminate.

Something like this (warning: untested code):

import multiprocessing
import time

SECONDS = 10
event = multiprocessing.Event()

def worker():
  """Does stuff until work is complete, or until signaled to terminate by timer."""
  while not event.is_set():
    if foo() == bar():
      break

def timer():
  """Signals the worker to terminate immediately."""
  time.sleep(SECONDS)
  event.set()

def main():
  """Kicks off subprocesses and waits for both of them to terminate."""
  worker_process = multiprocessing.Process(target=worker)
  timer_process = multiprocessing.Process(target=timer)
  timer_process.start()
  worker_process.start()
  timer_process.join()
  worker_process.join()

if __name__ == "__main__":
  main()

If you were worried about the foo and bar functions taking too long to complete, you could explicitly terminate the worker process from within the timer process.

like image 24
mpenkov Avatar answered Dec 30 '22 00:12

mpenkov