如何在Python中自动跳出死循环?

时间:2013-09-23 02:21:15

标签: python

我在Python中有一个“do ...,until ......”结构,如下所示:

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

在大多数情况下,它可以正常工作(最后跳出来)。但是,在一些从未遇到过这种情况的情况下,它会卡在那里。

弄清楚这些情况是什么有点困难,因为它本质上是一个随机的过程。所以我希望为while循环设置一个“超时”的东西。

假设,如果循环已经运行了1秒,但仍然没有停止,我希望循环终止。

我怎么能这样做?


更新:以下是实际代码:

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

3 个答案:

答案 0 :(得分:7)

import time

loop_start = time.time()
while time.time() - loop_start <= 1:
    if foo() == bar():
        break

答案 1 :(得分:5)

修改

Dan Doe的解决方案是最简单和最好的,如果您的代码是同步的(只在单个线程中运行)并且您知道foobar函数总是在一段时间。

如果您有异步代码(如GUI),或者用于测试终止条件的foobar函数本身需要很长时间才能完成,请继续阅读。

在单独的线程/进程中运行循环。在另一个进程中运行计时器。一旦计时器到期,设置一个标志,导致循环终止。

这样的事情(警告:未经测试的代码):

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()

如果您担心foobar函数需要很长时间才能完成,您可以在计时器进程中明确terminate工作进程

答案 2 :(得分:0)

我建议使用计数器。这是检测非收敛的常用技巧。

maxiter = 10000

while True:
  if stopCondition(): break

  maxiter = maxiter - 1
  if maxiter <= 0:
    print >>sys.stderr, "Did not converge."
    break

这需要最小的开销,并且通常最适合不同的CPU:即使在更快的CPU上,您也需要相同的终止行为;而不是基于时间的超时。

然而,如果你发现被卡住会更好,那就更好了。一些标准函数不再改进。