python 中断命令如果超时

5 投票
2 回答
7063 浏览
提问于 2025-04-17 14:27

可能重复的问题:
Python函数调用超时
如何在Python中设置函数超时,超时少于一秒

我在一个循环里运行一个函数,像这样:

for element in my_list:
    my_function(element)

但由于某些原因,有些元素可能会导致这个函数处理时间非常长(可能甚至会出现我无法追踪的无限循环)。所以我想加一些控制,让它在处理当前元素时,如果超过2秒就跳过它。这样该怎么做呢?

2 个回答

1

像这样:

import signal
import time

class Timeout(Exception): 
    pass 

def try_one(func,t):
    def timeout_handler(signum, frame):
        raise Timeout()

    old_handler = signal.signal(signal.SIGALRM, timeout_handler) 
    signal.alarm(t) # triger alarm in 3 seconds

    try: 
        t1=time.clock()
        func()
        t2=time.clock()

    except Timeout:
        print('{} timed out after {} seconds'.format(func.__name__,t))
        return None
    finally:
        signal.signal(signal.SIGALRM, old_handler) 

    signal.alarm(0)
    return t2-t1

def troublesome():
    while True:
        pass

try_one(troublesome,2)

这个函数 troublesome 是不会自己结束的。如果你用 try_one(troublesome,2),它会在2秒后成功超时。

2

我不太建议使用最明显的解决办法——也就是用signal.alarm()和一个信号处理器来异步地抛出异常,从而跳出任务执行。理论上这应该很好用,但实际上,cPython解释器的代码并不能保证处理器会在你想要的时间内执行。信号处理可能会因为一些字节码指令的执行而被延迟,所以即使你明确取消了警报(在try块之外),异常仍然可能在超时代码执行完后被抛出。

我们经常遇到的问题是,警报处理器的异常会在超时代码完成后才被抛出。

由于线程控制的选项不多,我通常依赖进程控制来处理需要设置超时的任务。基本上,就是把任务交给一个子进程,如果任务花费的时间太长,就杀掉这个子进程。multiprocessing.pool的功能并没有那么复杂,所以我自己做了一个控制池来实现这种控制。

撰写回答