I have found a code creating a timeout function here, which does not seem to work. The complete test code is below:
def timeout(func, args=(), kwargs={}, timeout_duration=1, default=None):
import threading
class InterruptableThread(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.result = None
def run(self):
try:
self.result = func(*args, **kwargs)
except:
self.result = default
it = InterruptableThread()
it.start()
it.join(timeout_duration)
if it.isAlive():
return default
else:
return it.result
def foo():
while True:
pass
timeout(foo,timeout_duration=3)
Expected behavior: code ends within 3 seconds. Where is the problem?
A thread can not gracefully kill another thread, so with your current code,
foonever terminates. (Withthread.daemon = Truethe Python program will exit when only daemon threads are left, but that does not allow you to terminatefoowithout also terminating the main thread.)Some people have tried to use signals to halt execution, but this may be unsafe in some cases.
If you can modify
foo, there are many solutions possible. For instance, you could check for athreading.Eventto break out of the while-loop.But if you can not modify
foo, you could run it in a subprocess using themultiprocessingmodule since unlike threads, subprocesses can be terminated. Here is an example of how that might look:yields
Note that this has some limitations too.
subprocesses receive a copy of the parent processes’ variables. If you modify a variable in a subprocess, it will NOT affect
the parent process. If your function
funcneeds to modify variables, you will need to use a shared variable.arguments (passed through
args) and keywords (kwds) must bepicklable.
want to create a multiprocessing Pool once at the beginning of a
program. This
timeoutfunction creates aPoolevery time you call it. This was necessary since we neededpool.terminate()toterminate
foo. There might be a better way, but I haven’t thought of it.