您可以使用普通的Python参数传递语法来指定crontab。例如,假设我们定义一个Event类如下所示:
from datetime import datetime, timedelta
import time
# Some utility classes / functions first
class AllMatch(set):
"""Universal set - match everything"""
def __contains__(self, item): return True
allMatch = AllMatch()
def conv_to_set(obj): # Allow single integer to be provided
if isinstance(obj, (int,long)):
return set([obj]) # Single item
if not isinstance(obj, set):
obj = set(obj)
return obj
# The actual Event class
class Event(object):
def __init__(self, action, min=allMatch, hour=allMatch,
day=allMatch, month=allMatch, dow=allMatch,
args=(), kwargs={}):
self.mins = conv_to_set(min)
self.hours= conv_to_set(hour)
self.days = conv_to_set(day)
self.months = conv_to_set(month)
self.dow = conv_to_set(dow)
self.action = action
self.args = args
self.kwargs = kwargs
def matchtime(self, t):
"""Return True if this event should trigger at the specified datetime"""
return ((t.minute in self.mins) and
(t.hour in self.hours) and
(t.day in self.days) and
(t.month in self.months) and
(t.weekday() in self.dow))
def check(self, t):
if self.matchtime(t):
self.action(*self.args, **self.kwargs)
(注:未经彻底测试)
然后你的CronTab可以在正常的python语法中指定:
c = CronTab(
Event(perform_backup, 0, 2, dow=6 ),
Event(purge_temps, 0, range(9,18,2), dow=range(0,5))
)
通过这种方式,您可以获得Python参数机制的全部功能(混合位置和关键字参数,并可以使用符号名称作为周和月的名称)
CronTab类将被定义为简单地按分钟增量休眠,并在每个事件上调用check()。(不过,夏令时/时区可能有一些微妙之处需要警惕)。下面是一个快速实现:
class CronTab(object):
def __init__(self, *events):
self.events = events
def run(self):
t=datetime(*datetime.now().timetuple()[:5])
while 1:
for e in self.events:
e.check(t)
t += timedelta(minutes=1)
while datetime.now() < t:
time.sleep((t - datetime.now()).seconds)
需要注意的几件事:Python的工作日/月份是零索引(不像cron),并且该范围不包括最后一个元素,因此像“1-5”这样的语法变成了范围(0,5)- ie[0,1,2,3,4]。如果您更喜欢cron语法,解析它应该不会太难。