Ви можете просто використовувати звичайний синтаксис, що передає аргумент Python, щоб вказати свій crontab. Наприклад, припустимо, що ми визначаємо клас події, як показано нижче:
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) - тобто [0,1,2, 3,4]. Якщо ви віддаєте перевагу синтаксису cron, розбір його не повинен бути надто складним.