Автор в блоге пишет.
So even more sophisticated “solutions” propose to ditch the Python-level-API and just brutally kill a thread with pthread_kill (on Unix) or TerminateThread (on Windows). This is a very
bad idea.
Придётся на multiprocessing переходить или на библиотеку гринлетов
Что-то вроде:
from multiprocessing.process import Process
import time
def func():
while True:
print "I am an unstoppable"
time.sleep(1)
result = None
timeout = 15
p = Process(target=func)
p.start()
# waiting for timeout
p.join(timeout)
print "timeout has elapsed or process has finished"
if p.is_alive():
p.terminate()
print "terminating the process"
time.sleep(10)
print "p.is_alive = %r" % p.is_alive()
И с получением результата от функции:
import multiprocessing
import time
resultq = multiprocessing.Queue(1)
def func1():
while True:
print "I am an unstoppable"
time.sleep(1)
#time.sleep(5)
return True
def func2():
time.sleep(5)
return "Result of func2"
def _func(func=None, func_args=()):
result = func(*func_args)
resultq.put(result)
def timedoutRun(func=None, f_args=()):
timeout = 10
result = None
p = multiprocessing.Process(target=_func, args=(func,)+f_args)
p.start()
# waiting for timeout
p.join(timeout)
print "timeout has elapsed or process has finished"
if resultq.empty():
print "We do not have a result of func because of the func gets stuck"
else:
print "process has competed"
result = resultq.get()
print "result is %r" % result
if p.is_alive():
p.terminate()
print "terminating the process"
time.sleep(10)
print "p.is_alive = %r" % p.is_alive()
return result
if __name__ == '__main__':
print "start"
print timedoutRun(func1)
print timedoutRun(func2)
print "end"
Не знаю как тут сделать правильно.
Пришлось держать глобальную очередь (которая может рассинхронизироваться при определённых условиях)