Задача: необходимо в отдельном потоке периодически запускать функцию, при этом нужно иметь возможность как можно быстрее завершить поток.
У меня было хорошее решение с использованием threading.Event, но как выяснилось у него слишком прожорливое ожидание таймаута. Поэтому пришел к такому костылю:
import threading
from select import select
import os
import time
class Timer(threading.Thread):
def __init__(self, interval, target, *args, **kwargs):
threading.Thread.__init__(self)
self.interval = interval
self.target = target
self.args = args
self.kwargs = kwargs
self.rfd = self.wfd = None
self.cancel_requested = False
def run(self):
self.rfd, self.wfd = os.pipe()
while True:
readable, _, exc = select([self.rfd], [], [], self.interval)
if self.cancel_requested:
break
self.target(*self.args, **self.kwargs)
def cancel(self, block=True):
self.cancel_requested = True
os.write(self.wfd, '1')
if block:
self.join()
os.close(self.rfd)
os.close(self.wfd)
def target(t):
print t[0]
t[0] += 1
t = Timer(2.0, target, [1])
t.start()
time.sleep(10.5)
t.cancel()
print 'done'
Может есть более элегантные способы добиться цели?