我正在使用threading.Timer
包在x秒后执行一个方法。但是,在某些情况下,我想更早地执行此方法并取消计时器(因此不会被调用两次)。 如何对此进行单元测试?
我想知道计时器是否已停止,以便不再调用该方法。我现在正在使用以下代码,不幸的是is_alive still
返回True
from threading import Timer
Class X():
def __init__(self, timeout):
self.timer = Timer(timeout, self.some_method)
self.timer.start()
def some_method(self):
# Do something
def other_method(self):
self.timer.cancel()
self.some_method()
import unittest
Class TestX(unittest.TestCase):
def test_cancel_timer(self):
x = X(1000)
x.other_method()
self.assertFalse(x.timer.is_alive())
在文档中,is_alive
方法在run
操作期间返回True;
返回线程是否处于活动状态。 该方法在run()方法开始之前直到run()方法终止之后才返回True。模块函数enumerate()返回所有活动线程的列表。
关于cancel
方法的文档中的内容如下:
停止计时器,并取消执行计时器的操作。仅当计时器仍处于等待状态时,此功能才起作用。
这是否意味着cancel
方法不会停止run
操作?还是在run方法之后仍处于灰色区域并因此返回True?
答案 0 :(得分:1)
使用timer.is_alive()
时,您只是在检查计时器线程本身是否还处于活动状态,因此,如果要“检查是否调用了timer.cancel()
”,则说明正在测试错误的内容。
这是否意味着cancel方法不会停止运行操作?
它不会停止run()
功能。 timer.cancel()
只是在Event
对象中设置一个标志,run
会对其进行检查。您可以测试标志是否设置为:
self.assertTrue(x.timer.finished.is_set())
不幸的是,检查取消还不足以防止重复执行,因为run
可能已经通过了检查,就像您在源代码中看到的那样:
# threading.py (Python 3.7.1): class Timer(Thread): """Call a function after a specified number of seconds: t = Timer(30.0, f, args=None, kwargs=None) t.start() t.cancel() # stop the timer's action if it's still waiting """ def __init__(self, interval, function, args=None, kwargs=None): Thread.__init__(self) self.interval = interval self.function = function self.args = args if args is not None else [] self.kwargs = kwargs if kwargs is not None else {} self.finished = Event() def cancel(self): """Stop the timer if it hasn't finished yet.""" self.finished.set() def run(self): self.finished.wait(self.interval) if not self.finished.is_set(): self.function(*self.args, **self.kwargs) self.finished.set()
需要更多的精力来确保唯一的执行。我已经在答案here中写出了一个可能的解决方案。