4

我在 Python 中有一个“做...,直到...”结构,如下所示:

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
4

3 回答 3

7
import time

loop_start = time.time()
while time.time() - loop_start <= 1:
    if foo() == bar():
        break
于 2013-09-23T02:26:26.883 回答
5

编辑

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

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

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

像这样的东西(警告:未经测试的代码):

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函数需要很长时间才能完成,您可以从计时器进程中显式终止工作进程

于 2013-09-23T02:24:01.437 回答
0

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

maxiter = 10000

while True:
  if stopCondition(): break

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

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

但是,如果您能检测到被卡住,例如某些不再改进的标准函数,那就更好了。

于 2013-09-24T08:05:39.687 回答