Timeout a function in python

Posted on 2018-06-02 in Trucs et astuces

You can use signals and a context manager to acheive this. The idea is to register a function that will raise an exeption when the alarm signal is received and schedule the alarm signal for the timeout.

import signal
from contextlib import contextmanager


@contextmanager
def timeout(time):
    # Register a function to raise a TimeoutError on the signal.
    signal.signal(signal.SIGALRM, raise_timeout)
    # Schedule the signal to be sent after ``time``.
    signal.alarm(time)

    try:
        yield
    except TimeoutError:
        pass
    finally:
        # Unregister the signal so it won't be triggered
        # if the timeout is not reached.
        signal.signal(signal.SIGALRM, signal.SIG_IGN)


def raise_timeout(signum, frame):
    raise TimeoutError


def my_func():
    # Add a timeout block.
    with timeout(1):
        print('entering block')
        import time
        time.sleep(10)
        print('This should never get printed because the line before timed out')

Even if this solution works well, you can't nest timeout which can be a problem. Perhaps a solution relying on concurrent.futures may work but during my tests, I never managed to correctly stop a function once a timeout has been reached.

Source: https://stackoverflow.com/a/494273/3900519