您可以只使用普通的 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”这样的语法变成了 range(0,5) - 即 [0,1,2, 3,4]。如果您更喜欢 cron 语法,那么解析它应该不会太难。