2

After spending a lot of hours looking for a solution in stackoverflow, I did not find a good solution to set a timeout for a block of code. There are approximations to set a timeout for a function. Nevertheless, I would like to know how to set a timeout without having a function. Let's take the following code as an example:

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

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

So, How would you break the for loop if it has not finished after x seconds? Just continue with the code (maybe saving some bool variables to know that timeout was reached), despite the fact that the for loop did not finish properly.

2 Answers 2

2

i think implement this efficiently without using functions not possible , look this code ..

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")

the problem : the timeout will checked in the beginning of every loop cycle, so it may be take more than the specified timeout period to break of the loop, or in worst case it maybe not interrupt the loop ever becouse it can't interrupt the code that never finish un iteration.


update :

as op replayed, that he want more efficient way, this is a proper way to do it, but using functions.

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())

Expected output:

doing thing here , it will take long time

timeout!

lets continue to do other things

note:

now timeout will happen after exactly the time you specify. in this example code, after one second.

you would replace this line:

await asyncio.sleep(3600)

with your actual task code.

try it and let me know what do you think. thank you.

read asyncio docs: link

update 24/2/2019

as op noted that asyncio.run introduced in python 3.7 and asked for altrnative on python 3.6

asyncio.run alternative for python older than 3.7:

replace

asyncio.run(main())

with this code for older version (i think 3.4 to 3.6)

loop = asyncio.get_event_loop()
loop.run_until_complete(main())
loop.close()
Sign up to request clarification or add additional context in comments.

5 Comments

The problem is what you are exactly saying, if "Doing some heavy stuff" doesn't finish, the loop isn't interrupted, what is exactly what I want to avoid.
i don't think you can implement this without having a function. sorry. but i would like to point you toward one way you could implement this correctly ( using functions ). i'll update my answer with the code in a minute. let me know what do you think.
I looks nice, but How can I get the return value of test_func()? I have been reading the docs and other stackoverflow questions, but I am not sure how to do it. On the other hand, asyncio.run seems to have been introduced in Python 3.7. What about doing it with python 3.6?
you can get returned value from the asynio function like normal function , result = await asyncio.wait_for(test_func(), timeout=1.0) . and i updated my answer to show alternative for asyncio.run for python 3.6
@vicase98 you are welcome, I'm glad I was able to help.
0

You may try the following way:

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')

I guess it is kinda viable approach. Actual timeout is greater than 3 seconds and depends on the single step execution time.

1 Comment

The problem is that I want to break the loop if ' #some heavy stuff' doesn't finish within x seconds, where x is my timeout. I mean, if it has not finished when timeout is reached, stop doing heavy stuff and break the loop

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.