【问题标题】:Timeout (and skip) a block of code inside a python iteration超时(并跳过)python迭代中的代码块
【发布时间】:2020-12-06 21:04:33
【问题描述】:

当循环中的某个步骤耗时过长时,如何跳过并继续?

以下是一些我想要的理想界面:

for x in some_collection:
    with Timeout(2.5):  # time out after 2.5 seconds
        do_something(x)

会很好(甚至更好——但可能会更难):

with TimeoutLoopStep(2.5):  # time out after 2.5 seconds
    for x in some_collection:
        do_something(x)

可能是一个等效的 timeout_loop_step 装饰器以这种方式使用迭代器:

timeout_loop_step(2.5)(map(do_something, some_collection))

--- 附录(编辑)以消除一些歧义---

我正在寻找的是一个上下文管理器和/或装饰器,如果它持续太长时间,它将中断迭代步骤的处理。

大多数与远程系统(例如 DB)通信的 API 都提供某种 timeout 参数,这意味着 “这样做,但如果您尝试超过 timeout,只需 phorgetaboutit 并继续下一项...”

但如果我没有提供这样的控制权,我想在外部使用可重用的上下文管理器或装饰器来实现它。

【问题讨论】:

  • 这能回答你的问题吗? How to implement a watchdog timer in Python?
  • @Steve,你的链接和汤姆的第一个链接一样。
  • @TomMyddeltyn,第二个不是我要找的。第一个可能,但我需要尝试将它放在我在问题中提到的一种形式中,看看它是否真的有效。我将在我的问题中添加更多详细信息,以明确我在寻找什么。
  • 不,Timer 解决方案 (WatchDog) 不是解决方案。计时器文档说“在指定的秒数后调用函数”。相比之下,我想要的是一种“在指定秒数后中断函数调用”的方法。

标签: python


【解决方案1】:

我很久以前就需要类似的东西。我的解决方案是一种基于线程的迭代器装饰器。 我把它放在pypi 上,名称为iterators。 对于您的情况,它看起来像这样。

from iterators import TimeoutIterator

m = map(do_something, some_collection)
it = TimeoutIterator(m, timeout=2.5)

for x in it:
  if x == None: # gives None if there is a timeout
    it.interrupt() # stop the underlying thread if breaking the loop
    break

或者,如果你的函数本身的结果可以是 None 那么你可以使用这样的东西:

from iterators import TimeoutIterator

m = map(do_something, some_collection)
it = TimeoutIterator(m, timeout=2.5,  sentinel=object())

for x in it:
  if x == it.get_sentinel(): # gives the sentinal object if there is a timeout
    it.interrupt()  # stop the underlying thread
    break

代码可能看起来很冗长,因为不幸的是,我从未想到使用上下文处理程序来停止底层线程的想法。那将消除调用中断的需要。我会在新版本中添加它。 对于我的情况,我需要继续迭代直到实际迭代器结束,但仍然能够确定我是得到结果还是超时。所以从不需要手动调用中断。

查看源代码中的其他选项和示例。

【讨论】:

    【解决方案2】:

    使用time模块:

    import time
    
    time_out = time.time()+2.5
    for x in some_collection:
        if time.time() == time_out:
            break
        do_something(x)
    

    【讨论】:

    • 对不起,我问的是一种“精益”方式来中断进程。上面尝试做的是暂停,您最好使用time.sleep(2.5)。此外,您的代码通常永远不会终止。我想你的意思是if time.time() >= time_out
    猜你喜欢
    • 2011-09-18
    • 2017-02-05
    • 2021-08-23
    • 2021-09-14
    • 1970-01-01
    • 2011-08-06
    • 2019-01-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多