您可以只使用普通的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)
(注意:未经彻底测试)
然后,可以使用普通的python语法将CronTab指定为:
c = CronTab(
Event(perform_backup, 0, 2, dow=6 ),
Event(purge_temps, 0, range(9,18,2), dow=range(0,5))
)
这样,您就可以充分利用Python的参数机制(混合使用位置和关键字args,并且可以将符号名称用于星期和几个月的名称)
将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”这样的语法变为range(0,5)-即[0,1,2, 3,4]。如果您喜欢cron语法,那么对其进行解析应该不会太困难。