如何为不是函数的代码块设置超时 python3

How to set timeout for a block of code which is not a function python3

在Whosebug上找了好几个小时的解决方案,也没找到好的解决方案,给一段代码设置超时时间。有一些近似值可以为函数设置超时。不过,我想知道如何在没有功能的情况下设置超时。我们以下面的代码为例:

    print("Doing different things")
    for i in range(0,10)
         # Doing some heavy stuff

    print("Done. Continue with the following code")

那么,如果 for 循环在 x 秒后仍未完成,您将如何中断它?继续代码(可能保存一些 bool 变量以知道超时已到),尽管 for 循环没有正确完成。

您可以尝试以下方式:

import time

start = time.time()
for val in range(10):
    # some heavy stuff
    time.sleep(.5)
    if time.time() - start > 3:  # 3 is timeout in seconds
        print('loop stopped at', val)
        break  # stop the loop, or sys.exit() to stop the script
else:
    print('successfully completed')

我想这是一种可行的方法。实际超时大于3秒,取决于单步执行时间。

我认为在不使用函数的情况下有效地实现这一点是不可能的,看看这段代码..

import datetime as dt
print("Doing different things")
# store 
time_out_after = dt.timedelta(seconds=60)
start_time = dt.datetime.now()
for i in range(10):
    if dt.datetime.now() > time_started + time_out:
        break
    else:
        # Doing some heavy stuff
print("Done. Continue with the following code")

问题:超时将在每个循环周期的开始检查,因此可能需要超过指定的超时时间才能中断循环,或者在最坏的情况下它可能不会中断循环因为它无法中断未完成 un 迭代的代码。


更新:

正如 op 重播的那样,他想要更有效的方法,这是一种正确的方法,但是使用函数。

import asyncio


async def test_func():

    print('doing thing here , it will take long time')
    await asyncio.sleep(3600) # this will emulate heaven task with actual Sleep for one hour
    return 'yay!' # this will not executed as the timeout will occur early


async def main():
    # Wait for at most 1 second
    try:
        result = await asyncio.wait_for(test_func(), timeout=1.0) # call your function with specific timeout
        # do something with the result
    except asyncio.TimeoutError:
        # when time out happen program will break from the test function and execute code here
        print('timeout!')
        print('lets continue to do other things')


asyncio.run(main())

预期输出:

doing thing here , it will take long time

timeout!

lets continue to do other things

注:

现在超时将在您指定的时间后发生。在此示例代码中,一秒钟后。

您将替换此行:

await asyncio.sleep(3600)

使用您的实际任务代码。

尝试一下,让我知道您的想法。谢谢。

阅读 asyncio 文档: link

更新 24/2/2019

正如 op 指出 asyncio.run 在 python 3.7 中引入并要求在 python 3.6

上提供替代方案

asyncio.run python 比 3.7 更早的替代方案:

替换

asyncio.run(main())

使用旧版本代码(我认为是 3.4 到 3.6)

loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()