2

I want to run some function, foo, and get the return value, but only if it take less than T seconds to run the function. Otherwise I'll take None as an answer.

The specific use case that created this need for me, is in running a series of sympy nonlinear solvers, which often hang. In searching the help for sympy, devs recommended not trying to do that in sympy. But, I could not find a helpful implementation that solved this problem.

florisvb
  • 61
  • 5

1 Answers1

2

This is what I ended up doing. If you have a better solution, please share!

import threading
import time

# my function that I want to run with a timeout
def foo(val1, val2):
    time.sleep(5)
    return val1+val2

class RunWithTimeout(object):
    def __init__(self, function, args):
        self.function = function
        self.args = args
        self.answer = None

    def worker(self):
        self.answer = self.function(*self.args)

    def run(self, timeout):
        thread = threading.Thread(target=self.worker)
        thread.start()
        thread.join(timeout)
        return self.answer

# this takes about 5 seconds to run before printing the answer (8)
n = RunWithTimeout(foo, (5,3))
print n.run(10)

# this takes about 1 second to run before yielding None
n = RunWithTimeout(foo, (5,3))
print n.run(1)
florisvb
  • 61
  • 5
  • Why not just `thread.join(timeout)` instead of the while-loop? – Michael Butscher Oct 20 '17 at 23:34
  • If the timeout was set to 10 seconds, but the function finished in 1 second, I think that without the while loop you'd be stuck waiting unnecessarily for 9 seconds. This way you get the result a little faster. Correct me if I'm wrong.. – florisvb Oct 22 '17 at 01:15
  • This is wrong, `thread.join()` returns as soon as either the timeout ran out or `thread` dies (which happpens when it completed its work). – Michael Butscher Oct 22 '17 at 02:52
  • Just checked myself and you are correct, that simplifies things. Will update the answer. Thanks! – florisvb Oct 23 '17 at 05:02