southernKid33
southernKid33

Reputation: 351

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

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.

Upvotes: 2

Views: 3812

Answers (2)

Sameh Farouk
Sameh Farouk

Reputation: 599

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

Upvotes: 2

user10325516
user10325516

Reputation:

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.

Upvotes: 0

Related Questions