【问题标题】:Aborting a loop after some time passes经过一段时间后中止循环
【发布时间】:2019-07-16 14:02:59
【问题描述】:

我的代码可能会陷入长循环。这些不是无限循环,但某些输入可能会导致循环持续很长时间。我希望使用中断以防循环太长。有了这个中断,循环将重新评估它的输入,所以键盘中断不是我想要的。我在 Windows 上使用 python 2.7。

一种可能的方法是使用 time.time() 进行轮询,但效率极低。循环本身并不长,但是即使在正常运行中它也会迭代 100k 次,所以我无法在每次迭代后轮询时间,这会大大降低效率。或者,我可以介绍更多变量,

i=0
while i<some_very_large_number:
    function(foo, foo1, foo2)
    i=i+1

但这又是一个平庸的解决方案。

简而言之,我要找的是一些相当于微处理器硬件中断的python。我没有多线程的经验,所以如果答案在于多线程,请详细说明。

我检查了herehere,但我认为他们没有回答我的问题。第二个链接实际上可以提供帮助,但显然信号包在 Windows 中不可用。

代码很长但很简单。基本上就是这样的结构。

def function(foo, foo1, foo2, N):
    for i in range(N):
        performance = performance_evaluator(foo, foo1, foo2)
        if performance_takes_too_long:
             interrupt ##this if clause is the main objective of this question##
        record performance
        new_foo, new_foo1, new_foo2 = evolve(foo, foo1, foo2)

【问题讨论】:

  • 使用time有什么问题?是不是它会给你的代码增加比你想要的更多的运行时间?
  • @blackbrandt 谢谢,但信号文档说它仅在 UNIX 中可用。不是这样吗?我会混淆吗?
  • “一种可能的方法是使用 time.time() 进行轮询,但效率极低” 你到底是什么意思?它如何或为什么效率低下?似乎这里最合理的方法是将函数开始时的时间保存在变量中,并在每次迭代时测量经过的时间,然后如果经过的时间太大,则引发异常或其他情况。那不适合你吗?
  • @C.Koca 您在 Windows 平台上吗?如果是这样,那将很重要,您应该将其放在原始帖子中。
  • @blackbrandt 是的,我试图在问题中暗示它,但我会明确说明。

标签: python


【解决方案1】:

一种可能的方法是修改您的脚本,使其通过命令行参数获取输入,然后使用subprocess 模块在超时的情况下运行它:

# manager.py
import subprocess

try:
    code = subprocess.call('python work.py 5', timeout=2)
    print('Ended with code:', code)
except subprocess.TimeoutExpired:
    print('Ended with timeout')


# work.py
import sys
from time import sleep

try:
    wait = int(sys.argv[1])
except:
    wait = 10

sleep(wait)
print(f'Waited for {wait} seconds')

输出:

Ended with timeout

【讨论】:

    【解决方案2】:

    您还可以在单​​独的工作进程中执行长时间运行的代码,并在超过超时且工作人员尚未完成时尝试终止它:

    import time
    from multiprocessing import Process
    
    
    def process_data():
    
        while True:
            print("processing...")
            time.sleep(1)
    
    
    def main():
        worker = Process(target=process_data)
        worker.start()
    
        timeout = 5
        time.sleep(timeout)
    
        if worker.is_alive():
            print("exceeded timeout", timeout, "sec")
            print("terminate worker", worker)
            worker.terminate()
    
        worker.join()
        print("is worker", worker, "alive:", worker.is_alive())
    
    
    if __name__ == "__main__":
        main()
    

    这是输出:

    processing...
    processing...
    processing...
    processing...
    processing...
    exceeded timeout 5 sec
    terminate worker <Process(Process-1, started)>
    is worker <Process(Process-1, stopped[SIGTERM])> alive: False
    

    【讨论】:

      最近更新 更多