【问题标题】:Function Timeout API for PythonPython 函数超时 API
【发布时间】:2014-10-29 17:44:28
【问题描述】:

我正在尝试实现一个函数,如果它无法在一定时间内完成(线程挂起问题),它将超时。这个answer 似乎是最有前途的,它有效地提供了一个API 包装器来调用我的实际函数。它通常似乎可以工作(请参阅 loop_forever),但是当我使用 time.sleep 时无法停止。为什么超时不适用于睡眠定时器,这是否可以作为防止线程挂起的一种方式?

import signal
import time

def timeout(func, args=(), kwargs={}, timeout_duration=1, default=None):


    class TimeoutError(Exception):
        pass

    def handler(signum, frame):
        raise TimeoutError()

    # set the timeout handler
    signal.signal(signal.SIGALRM, handler) 
    signal.alarm(timeout_duration)
    try:
        result = func(*args, **kwargs)
    except TimeoutError as exc:
        result = default
    finally:
        signal.alarm(0)

    return result




def loop_forever():
    x = 0
    while True:
        print x
        try:
            x += 1
        except:
            continue

def loop_forever_sleep():
    x = 0
    while True:
        print x
        try:
            x += 1
            time.sleep(10)
        except:
            continue

if __name__ == '__main__':
    a = timeout(loop_forever) #Terminates
    b = timeout(loop_forever_sleep) #Does not terminate

【问题讨论】:

  • 你的目标是什么平台?
  • 这是在Linux上,我知道这个功能在Windows上不起作用。

标签: python multithreading timeout


【解决方案1】:

问题是SIGALRM 在您处于time.sleep(10) 系统调用内部时被引发,这也会导致您的handler 在该上下文中被调用。但是,您正在吞噬无限循环中发生的所有异常,因此TimeoutError 永远不会返回到timeout 函数,而是被loop_forever_sleep 中的except: continue 代码忽略。只需从 while True 循环中删除 try/except 块,它就可以正常工作:

def loop_forever_sleep():
    x = 0
    while True:
        print x
        x += 1
        time.sleep(10)

【讨论】:

  • 这意味着任何时候在 try 块中发生超时都不会返回 API,只需结束该 try 块?
  • @Michael 如果您使用裸except 块,这将捕获TimeoutError,是的。您需要仅捕获您在 try 块中预期的特定异常,或者如果您捕获它,则始终重新引发 TimeoutError
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-20
  • 1970-01-01
  • 2012-06-18
  • 2022-08-19
  • 1970-01-01
  • 2017-06-13
相关资源
最近更新 更多