Timeout when a function takes too long to complete

Asked 2 years ago, Updated 2 years ago, 18 views

In order to visit the sites you want to take screenshots, we created a shell script that reads text files sequentially, including URLs for those sites.

First of all, I implemented it simply without any problems. The script initializes the class that visits each site listed and takes screenshots. However, some sites take quite a long time to complete loading, and some failed to load at all. So, if you can't complete the task in 10 seconds, you want to wrap the function that takes a screenshot with a timeout script so that you can return False.

Setting an asynchronous timer that returns False after 10 seconds, or how the function works internally, can be a simple solution.

python

2022-09-22 11:09

1 Answers

The process for timing out commands is described in the documentation related to signal.

The basic idea is to use a signal handler that sets alarms at a specific time interval to generate an exception over time.

Note that this method works only with UNIX.

The code below is the code that generates the decorator. (Save it as timeout.py)

from functools import wraps
import errno
import os
import signal

class TimeoutError(Exception):
    pass

def timeout(seconds=10, error_message=os.strerror(errno.ETIME)):
    def decorator(func):
        def _handle_timeout(signum, frame):
            raise TimeoutError(error_message)

        def wrapper(*args, **kwargs):
            signal.signal(signal.SIGALRM, _handle_timeout)
            signal.alarm(seconds)
            try:
                result = func(*args, **kwargs)
            finally:
                signal.alarm(0)
            return result

        return wraps(func)(wrapper)

    return decorator

The above code creates a decorator that can invoke @timeout that can be applied to any function of long operation.

Therefore, this decoration can be used for the code of the person who asked the question as follows:

from timeout import timeout

# Time out the function after the default expiration time of 10 seconds
@timeout
def long_running_function1():
    ...

# Time out in 5 seconds
@timeout(5)
def long_running_function2():
    ...

# Timeout after 30 seconds with error "Connection timed out"
@timeout(30, os.strerror(errno.ETIMEDOUT))
def long_running_function3():
    ...


2022-09-22 11:09

If you have any answers or tips


© 2024 OneMinuteCode. All rights reserved.