python function execution deadlines - in simple examples

Sometimes a Python method call will take a long time (even forever) to return a value. This isn't a good thing -- it can block your server, or take up lots of wasted time on the CPU. Thankfully, it's easy to limit the amount of time that functions can execute for using python's signal module.

Here, a function is only allowed to execute for 5 seconds:

import signal

def handler(signum, frame):
    print 'Signal handler called with signal', signum

# Set the signal handler and a 5-second alarm
signal.signal(signal.SIGALRM, handler)
signal.alarm(5)

# This function may hang indefinitely
takes_a_long_time()

signal.alarm(0)

Something nicer using function decorators

It's nice to be able to do this, but we can do better. Copying that same logic into each function we'd like to deadline would be bad design. Thankfully, Using Python's decorator syntax, we can decorate particular methods that we want to give deadlines to as easily as this:

@deadline(5)
def f():
  ...

Snippets to do this can be found online (here) but they use old Python syntax, which might result in the following error:

AttributeError: 'str' object has no attribute 'func_name'

Here is the corrected code that works in more recent versions of python (like 2.7):

class TimedOutExc(Exception):
  pass

def deadline(timeout, *args):
  def decorate(f):
    def handler(signum, frame):
      raise TimedOutExc()

    def new_f(*args):

      signal.signal(signal.SIGALRM, handler)
      signal.alarm(timeout)
      return f(*args)
      signa.alarm(0)

    new_f.__name__ = f.__name__
    return new_f
  return decorate

Now, we can easily "decorate" any function with a deadline. In this case, we'd want to not let the function run for more than 5 seconds:

@deadline(5)
def take_a_long_time():
  while(True):
    pass

If you want to catch the exception rather than halting all program execution, just do it like you catch any other exception:

try:
  take_a_long_time()
except TimedOutExc as e:
  print "took too long"

Be careful when using these kinds of signal-based deadlines in multiprocressing or multithreaded functions. Read more here if you are having trouble with that