【发布时间】:2018-04-27 17:55:36
【问题描述】:
我知道这听起来很像this similarly-worded question,但也有区别,请耐心等待。
我正在尝试创建一个可重用的“计时器”类,它每 N 秒调用一次指定的回调,直到您调用 stop。作为灵感,我使用了上面的链接,并在 stop 方法中包含了一个内置事件。下面是基本类的外观:
import time
import threading
from threading import Thread
from threading import Event
# Mostly inspired by https://stackoverflow.com/questions/12435211/python-threading-timer-repeat-function-every-n-seconds
class RepeatingTimer(Thread):
def __init__(self, interval_seconds, callback):
Thread.__init__(self)
self.stop_event = Event()
self.interval_seconds = interval_seconds
self.callback = callback
self.setDaemon(True)
def start(self):
while not self.stop_event.wait(self.interval_seconds):
self.callback()
time.sleep(0) # doesn't seem to do anything
def stop(self):
self.stop_event.set()
看起来不错,甚至包括基于this question 的time.sleep(0)。
这和我想的不一样;对start 的调用似乎永远不会返回或屈服。考虑这个用例:
def print_status(message):
print(message)
def print_r1():
print_status("R1")
def print_r2():
print_status("R2")
r1 = RepeatingTimer(1, print_r1)
r2 = RepeatingTimer(0.5, print_r2)
r1.start()
r2.start()
对r1.start 的调用永远不会终止。它永远持续下去。四秒后控制台上的输出是:
R1
R1
R1
R1
这促使我介绍了time.sleep(0) 调用,尽管这似乎没有任何作用。
我也尝试过使用和不使用self.setDaemon(True),但这似乎也没有效果。
我还尝试将其转换为两个类:一个仅包含事件包装器(StoppableTimer 类),另一个仅在回调中创建和重新创建 StoppableTimer,但这也不起作用。这是它的样子:
class StoppableTimer(Thread):
def __init__(self, interval_seconds, callback):
Thread.__init__(self)
self.stop_event = Event()
self.interval_seconds = interval_seconds
self.callback = callback
self.setDaemon(True)
def start(self):
time.sleep(self.interval_seconds)
self.callback()
def stop(self):
self.stop_event.set()
class RepeatingTimer:
def __init__(self, interval_seconds, callback):
self.interval_seconds = interval_seconds
self.callback = callback
self.timer = StoppableTimer(interval_seconds, self.refresh_timer)
def start(self):
self.timer.start()
def stop(self):
self.timer.stop()
def refresh_timer(self):
self.stop()
self.callback()
self.timer = StoppableTimer(self.interval_seconds, self.refresh_timer)
self.timer.start()
我完全不知道如何进行这项工作。我也主要是 Python 的初学者,所以请在你的答案中添加足够的解释,以便我了解根本问题是什么。
我还阅读了一些关于 Global Interpreter Lock on SO 的信息,但我不明白这怎么会是个问题。
作为参考,我在 Ubuntu 17.10 上运行 Python 3.6.3
【问题讨论】:
-
您似乎已经覆盖了
Thread的start方法,您可以想象,这不是一个好主意,尤其是如果您从未调用实际的 Thread.start 时 -
@pvg 这可能是我在这里对 Python 的缺乏经验。我从字面上复制粘贴了链接线程中的代码,并对其进行了修改以使事件成为成员变量而不是外部性。我将做一个注释以编辑链接问题中的代码示例。
-
你没有,我检查了:)。您已经重写了代码,使其无法正常工作。有人会注意到它在原始答案中不起作用并指出来。
-
@pvg 我复制粘贴了它,但在某些时候,我将
run重命名为start(没有意识到它的含义)。这可能解释了反对票...
标签: python python-3.x python-multithreading