检查超时条件的python方法

时间:2018-12-07 08:46:40

标签: python loops conditional-statements

我需要在超时之前检查特定条件。如果在限制之前满足条件,则返回True,否则返回False。

我正在通过以下方式

counter = 1
condition_met = False
while counter < max_limit:
    if <conditions are met>:
        condition_met = True
        break
    time.sleep(10)
    counter += 1
return condition_met

我想知道是否还有一种更Python化的方式来做同样的事情。

提前感谢您的反馈

4 个答案:

答案 0 :(得分:2)

如果不是time.sleep,则您的循环将等效于

for _ in range(max_limit):
    if <condition>:
        return True
    # time.sleep(10)
return False

相当于return any(<condition> for _ in range(max_limit)

因此,您可以({)}使用anyor来检查条件是否满足特定的次数,同时在每次检查之前稍作等待:

any(time.sleep(10) or <condition> for _ in range(max_limit))

这将首先评估time.sleep,并返回None,然后评估条件,直到满足条件或range用完为止。

唯一的警告是,即使在第一次检查条件之前,它也会调用time.sleep。要解决此问题,您可以先检查计数器变量,仅在该变量为> 0时调用time.sleep

any(i and time.sleep(10) or <condition> for i in range(10))

是否要比长循环更明确?


按照建议的in comments,实际上您可以将上面的any子句转换为

any(<condition> or time.sleep(10) for _ in range(max_limit))

这将首先检查条件,并且只有条件为假时,sleep才会进行检查。比上面两个方法中的任何一个都更自然地准备好了。

答案 1 :(得分:2)

计时的一种非常好的方法是使用- shock -time模块:

import time

def foo():
    max_limit = 25  # Seconds.

    start = time.time()
    condition_met = False
    while time.time() - start < max_limit:
        if <conditions are met>:
            condition_met = True
            break
        time.sleep(10)

    return condition_met

看到了吗?该模块不仅仅可以sleep来实现。 ;¬)

答案 2 :(得分:1)

我假设您在函数中有代码。 以下代码摆脱了变量condition_metbreak语句。

counter = 1
# condition_met = False
while counter < max_limit:
    if <conditions are met>:
        # condition_met = True
        return True   # get rid of break statement
    time.sleep(10)
    counter += 1
return False

答案 3 :(得分:0)

这是另一种方法,它结合使用 threading.Timer 和函数装饰器来了解何时超过给定的时间限制。

我将@Aaron Hall 的 answer 中的方法改编为一个非常相似的 Timeout on a function call 问题,因此可以在不杀死进程中的主线程(即调用者)的情况下使用它。

在此方案中,创建一个 Timer 对象以在经过 quit 秒后调用 time_limit 函数。如果发生这种情况,quit 函数会打印出一条通知消息,然后通过调用 _thread.interrupt_main() 引发 KeyboardInterrupt 异常。包裹在原始函数周围的 decorator() 函数捕获了这个异常,并使得该函数看起来好像返回了 False — 相反,如果没有发生这种情况,它会取消 Timer 线程并返回 { {1}}。

True

在指定时间内满足条件时打印:

from random import randint
import sys
import time
import threading
import _thread as thread  # Low-level threading API


def interupt_after(time_limit):
    ''' Decorator to raise KeyboardInterrupt if function takes more than
        `time_limit` seconds to execute.
    '''
    def quit_func(func_name):
        print('{0}() took too long'.format(func_name), file=sys.stderr)
        sys.stderr.flush()
        thread.interrupt_main()  # Raises KeyboardInterrupt.

    def decorator(func):
        def decorated(*args, **kwargs):
            timer = threading.Timer(time_limit, quit_func, args=[func.__name__])
            timer.start()
            try:
                func(*args, **kwargs)  # Note return value ignored.
            except KeyboardInterrupt:
                return False
            finally:
                timer.cancel()
            return True
        return decorated

    return decorator


if __name__ == '__main__':

    @interupt_after(5)
    def foo(lo, hi):
        mid = (lo+hi) // 2
        condition_met = False
        while not condition_met:
            if randint(lo, hi) == mid:  # Condition to meet.
                condition_met = True
                break
            time.sleep(1)

        return condition_met

    print(f'foo(40, 44):', foo(40, 44))
    print('-fini-')

如果不是这样:

foo(40, 44): True
-fini-