python3 sched:在运行()之后安排事件
使用python3 sched:在运行()之后安排事件,python,python-3.x,Python,Python 3.x,使用计划程序计划事件时。在调用计划程序后输入。运行直到至少触发一个在运行计划程序之前输入的事件,才会触发这些事件。这是有意的吗 import sched import threading import time now = time.time() scheduler = sched.scheduler(time.time, time.sleep) def fire(name): print('EVENT:', name, time.time() - now) def star
计划程序计划事件时。在调用计划程序后输入
。运行
直到至少触发一个在运行计划程序之前输入的事件,才会触发这些事件。这是有意的吗
import sched
import threading
import time
now = time.time()
scheduler = sched.scheduler(time.time, time.sleep)
def fire(name):
print('EVENT:', name, time.time() - now)
def start():
t = threading.Thread(target=scheduler.run)
t.start()
###################################
# when scheduling all before start() everything works as expected.
# scheduler.enter(4, 1, fire, ('D',))
# scheduler.enter(3, 1, fire, ('C',))
# scheduler.enter(2, 1, fire, ('B',))
# scheduler.enter(1, 1, fire, ('A',))
# start()
#
# EVENT: A 1.0
# EVENT: B 2.0
# EVENT: C 3.0
# EVENT: D 4.0
###################################
# here I'd expect event 'A' to fire after one second. But it is
# not fired until at least one of the events scheduled before run()
# is fired.
# scheduler.enter(2, 1, fire, ('B',))
# scheduler.enter(4, 1, fire, ('D',))
# start()
# scheduler.enter(1, 1, fire, ('A',))
# scheduler.enter(3, 1, fire, ('C',))
#
# EVENT: A 2.005021572113037
# EVENT: B 2.005021572113037
# EVENT: C 3.0050315856933594
# EVENT: D 4.0050413608551025
###################################
# starting before any event is scheduled is not possible,
# because run() returns directly.
#
# start()
# scheduler.enter(3, 1, fire, ('C',))
# scheduler.enter(2, 1, fire, ('B',))
# scheduler.enter(1, 1, fire, ('A',))
#
# -- no events fired.
启动调度程序时,它会找到直到下一个事件的延迟,并使用该值调用delayfunc(
time.sleep()
)。在delayfunc返回之前,计划程序无法触发任何其他事件
使用
sched
模块,我看不出有什么办法可以解决这个问题。它的设计似乎基于这样一种想法,即新事件将从现有事件的处理程序中添加,而不是从单独的线程中添加(事实上,直到Python 3.3,它甚至不支持在多线程环境中使用)。使用新的async
可能有更好的方法,但我没有任何特别的建议。请记住,如果您可以将任务分解为定期重复的固定作业,您也可以使用schedule
但在这种情况下,我的解决方案是将调度器子类化,如图所示,使用廉价的私有函数进行轮询。这使调度程序成为永久性的,并且它“听到”更新至少达到(至少)轮询间隔的粒度。我已经设置了一个可配置的投票率,默认为每秒4次——这对于GUI反馈很好。在生产环境中,运行的线程应该是守护进程,这样它就不会干扰终止请求。这是您的代码的修改版本。准备好使用时,从轮询中删除打印('tick')
import sched
import threading
import time
now = time.time()
class scheduler_with_polling(sched.scheduler):
def __init__(self, timefn, waitfn, **kwargs):
super().__init__(timefn, waitfn)
self.polling_interval = kwargs.get('polling_interval', 0.25)
def run(self):
self.enter(self.polling_interval, 1, self.__poll)
super().run()
def __poll(self):
print('tick') # remove for production
self.enter(self.polling_interval, 1, self.__poll)
pass
scheduler = scheduler_with_polling(time.time, time.sleep, polling_interval=0.2)
def fire(name):
print('EVENT:', name, time.time() - now)
def start():
t = threading.Thread(target=scheduler.run) # use daemon=True for production
t.start()
scheduler.enter(2, 1, fire, ('B',))
scheduler.enter(4, 1, fire, ('D',))
start()
scheduler.enter(1, 1, fire, ('A',))
scheduler.enter(3, 1, fire, ('C',))