我在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
答案 0 :(得分:7)
import time
loop_start = time.time()
while time.time() - loop_start <= 1:
if foo() == bar():
break
答案 1 :(得分:5)
修改强>
Dan Doe的解决方案是最简单和最好的,如果您的代码是同步的(只在单个线程中运行)并且您知道foo
和bar
函数总是在一段时间。
如果您有异步代码(如GUI),或者用于测试终止条件的foo
和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()
如果您担心foo
和bar
函数需要很长时间才能完成,您可以在计时器进程中明确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上,您也需要相同的终止行为;而不是基于时间的超时。
然而,如果你发现被卡住会更好,那就更好了。一些标准函数不再改进。