使用Twisted的Deferred和循环调用模拟crontab
我想在我的Twisted应用程序中实现类似定时任务的功能。具体来说,我希望能定期触发一个调用(比如每周一次),但只在特定的时间执行,而不是在我启动应用程序的时候就执行。
我的需求是这样的:我的Python应用程序可以在一周中的任何时间启动。我希望这个调用能在每周一的早上8点执行。但我不想使用主动等待(比如用time.sleep()),我想用callLater来触发下一个周一的调用,然后从那时开始进行循环调用。
有没有什么想法或建议?谢谢,J。
2 个回答
1
如果我理解你的问题没错的话,你是在想一个定时任务第一次执行的时候,怎么给应用程序提供一个初始的开始时间。如果是这样的话,你只需要计算出一个时间差的值(以秒为单位),然后把这个值传给callLater就可以了。
import datetime
from twisted.internet import reactor
def cron_entry():
full_weekseconds = 7*24*60*60
print "I was called at a specified time, now you can add looping task with a full weekseconds frequency"
def get_seconds_till_next_event(isoweekday,hour,minute,second):
now = datetime.datetime.now()
full_weekseconds = 7*24*60*60
schedule_weekseconds = ((((isoweekday*24)+hour)*60+minute)*60+second)
now_weekseconds=((((now.isoweekday()*24)+now.hour)*60+now.minute)*60+now.second)
if schedule_weekseconds > now_weekseconds:
return schedule_weekseconds - now_weekseconds
else:
return now_weekseconds - schedule_weekseconds + full_weekseconds
initial_execution_timedelta = get_seconds_till_next_event(3,2,25,1)
"""
This gets a delta in seconds between now and next Wednesday -3, 02 hours, 25 minutes and 01 second
"""
reactor.callLater(initial_execution_timedelta,cron_entry)
reactor.run()
7
如果你非常喜欢那种cron风格的时间设置方式,你可以考虑使用parse-crontab这个工具。
这样你的代码看起来基本上是这样的:
from crontab import CronTab
monday_morning = CronTab("0 8 * * 1")
def do_something():
reactor.callLater(monday_morning.next(), do_something)
# do whatever you want!
reactor.callLater(monday_morning.next(), do_something)
reactor.run()