根据我的理解,python stdlib中没有这样的开箱即用的解决方案。
解决方案必须具备以下特征:
我在SO上遇到了一些建议,但是想在这里汇总所有收集到的知识(我会在后续回答中做出贡献),以便听取任何新的或替代的或额外的想法。
答案 0 :(得分:0)
我的提案使用threading
库,因为它的广告级别高于thread
。
中间立场是这个解决方案,从其他SO回答中找到:
def main():
t_stop= threading.Event()
t = threading.Thread(target=thread, args=(1, t_stop))
t.daemon = True
t.start()
time.sleep(duration)
#stop the thread
t_stop.set()
def thread(arg, stop_event):
while(not stop_event.is_set()):
# Code to execute here
stop_event.wait(time)
遗憾的是,这需要我们在测试时使用t_stop
对象 - 以便停止线程 - 并且对象的句柄不会被暴露。
解决方案是在某个顶级或全局字典中添加t
和t_stop
句柄,以便测试代码到达。
另一种解决方案(从某处复制和改进)是使用以下内容:
def main():
t = DaemonStoppableThread(sleep_time, target=target_function,
name='polling_thread',
args=(arg1, arg2))
t.start()
# Stopping code from a test
def stop_polling_threads():
threads = threading.enumerate()
polling_threads = [thread for thread in threads
if 'polling_thread' in thread.getName()]
for poll_thread in polling_threads:
poll_thread.stop()
class DaemonStoppableThread(threading.Thread):
def __init__(self, sleep_time, target=None, **kwargs):
super(DaemonStoppableThread, self).__init__(target=target, **kwargs)
self.setDaemon(True)
self.stop_event = threading.Event()
self.sleep_time = sleep_time
self.target = target
def stop(self):
self.stop_event.set()
def stopped(self):
return self.stop_event.isSet()
def run(self):
while not self.stopped():
if self.target:
self.target()
else:
raise Exception('No target function given')
self.stop_event.wait(self.sleep_time)
与这些解决方案一样好,它们都不会面临重新启动轮询目标功能。
我避免使用表达式"重新启动线程",因为我知道python线程无法重新启动,所以必须使用新线程来允许这个"伪重启&#34 ;
编辑:
为了改进上述内容,多次启动/停止轮询目标的解决方案:
class ThreadManager(object):
def __init__(self):
self.thread = None
def start_thread(self):
if not self.thread or not self.thread.is_alive():
self.thread = DaemonStoppableThread(sleep_time=5, target=some_func, args=(1, 2))
self.thread.start()
return 'thread running'
def stop_thread(self):
if self.thread and self.thread.is_alive():
self.thread.stop()
return 'thread stopped'
else:
return 'dead thread'
def check_thread(self):
if self.thread and self.thread.is_alive():
return 'thread alive'
else:
return 'dead_thread'