我让一个函数在循环中不断运行,检查它是否应该启动或取消在函数作用域中定义的计时器。需要在函数中定义计时器,因为回调也在函数中定义。我可以很好地启动计时器,但当它试图取消时,我得到一个错误‘本地变量’计时器‘赋值前引用’。
我尝试在全局作用域中定义计时器及其回调(这是不可取的),但我得到另一个错误“线程只能启动一次”。
import threading
import random
def start():
trigger = random.randint(0,1)
def do_something():
print(trigger)
if trigger == 0:
timer = threading.Timer(2,do_something)
timer.start()
else:
timer.cancel() #: if trigger is 1, I want to cancel the timer
threading.Timer(1,start).start() #: start() is in a loop and is constantly checking trigger's value
start()
我希望根据触发器的值启动或取消相同的计时器。计时器和它的回调应该在函数中定义。
发布于 2019-05-13 00:37:41
这个程序展示了如何使用随机数来启动或停止计时器。
如果随机数连续选择0
足够多的次数,定时器将被启动,并被允许继续计时,直到时间耗尽并调用其目标。
如果随机数选择1
,则取消计时器,并且不调用目标:
import threading
import random
import time
class Timing:
def __init__(self):
self.timer = None # No timer at first
self.something = None # Nothing to print at first
self.restart()
def restart(self):
self.run = threading.Timer(1.1, self.start)
self.run.start()
def cancel(self):
if self.run is not None:
self.run.cancel()
self.run = None
def start(self):
trigger = random.randint(0, 1)
self.do_start(trigger)
def do_start(self, trigger):
print('start', trigger)
if trigger == 0:
if self.timer is None:
self.something = trigger
self.timer = threading.Timer(2, self.do_something)
self.timer.start()
else:
if self.timer is not None:
self.timer.cancel()
self.timer = None
self.something=None
self.restart()
def do_something(self):
print(self.something)
t = Timing()
print('sleeping...')
time.sleep(20)
t.cancel()
t.do_start(1)
t.cancel()
print('Done')
样本输出(ymmv,因为它是随机的)
sleeping...
start 1
start 0
start 1
start 0
start 0
0
start 1
start 0
start 1
start 1
start 1
start 1
start 1
start 0
start 1
start 0
start 0
0
start 1
start 0
start 1
Done
发布于 2019-05-13 00:59:53
我从@quamrana和@smci学到了这个
import threading
import random
class Timer():
pass
t = Timer()
def start():
trigger = random.randint(0,1)
def do_something():
print(trigger)
if trigger == 0:
t.timer = threading.Timer(1,do_something)
t.timer.start()
else:
if hasattr(t,'timer'):
t.timer.cancel()
threading.Timer(1,start).start()
start()
这似乎在保持代码紧凑的同时解决了这个问题。
https://stackoverflow.com/questions/56100848
复制相似问题