それはすべて、実行中の cronjob を実際にどのように実装しているかによって異なります。しかし、イベントが他のイベントを変更できるようにしたい場合は、3 つのオプションを考えることができます。
1. cron への参照を関数に渡します
CronTab クラスは、イベントがそれを「検査」できる方法を提供する必要があります。最良のオプションは、キーワード引数を「cron」引数で拡張し、次のように関数に渡すことです。
class CronTab(object):
def __init__(self, *events):
self.events = events
for event in self.events:
event.kwargs['cron'] = self
# rest of the calss remains unmodified
そうすることで、実行中の Crontab から呼び出されるすべての関数に、それを実行している cron への参照を含む「cron」パラメーターが渡されます。
2.「プレラン」マーシャルを追加します
CronTab クラスを拡張して、特定のスケジュールでイベントを実行するだけでなく、それらのイベントの前に他の関数を呼び出すこともできます。イベントのインスタンスを取得し、True
それを実行するために戻る必要がある関数。それらのいずれかが他の何かを返す場合、問題のイベントは実行されません。
そのための基本的な(そしてテストされていない)実装は次のようになります。
class CronTab(object):
def __init__(self, *events, marshalls=None):
self.events = events
if marshalls is not None:
# marshalls must be a list of callables that return True or False
self.marshalls = marshalls
else
self.marshalls = []
def run(self):
t=datetime(*datetime.now().timetuple()[:5])
while 1:
for e in self.events:
if all([x(e) for x in self.marshalls]):
e.check(t)
t += timedelta(minutes=1)
while datetime.now() < t:
time.sleep((t - datetime.now()).seconds)
明らかにこれを実装するためのより良い方法があります。たとえば、reduce
操作を実行して、いずれかのイベントが False を返した後で、すべてのイベントのすべてのマーシャルを実行しないようにします。しかし、これはあなたを正しい方向に向けるはずです。
CronTab クラスが実際にイベントのインスタンスを呼び出すよりも多くの作業を行った場合、check
または少なくとも実行のチェックを実際のイベントの実行に分離した場合、これを実装する方が簡単かもしれませんが、元のコードを変更したくありませんでした。それだけ。
3. イベントにフックを提供する
これは基本的に前のソリューションと同じですが、より「きめの細かい」ソリューションです。実行前のマーシャルのリストを 1 つだけ持つ代わりに、複数のリストを持つことになります。あなた自身のニーズに合わせて調整できる正確な量と詳細ですが、ここではあなたの要求に基づいた私の見解を示します.
一般的な「プレラン マーシャル」に加えて、イベント名ごとにそのようなリストを 1 つ持つことができます。イベントを実行する前に、すべての一般的な「プレラン マーシャル」だけでなく、イベント固有のものも実行します。
これを実装する 1 つの方法は、「事前実行マーシャル」リストをリストの辞書にして、そのようなリストを管理するいくつかのメソッドを提供することです。このようなもの:
class CronTab(object):
def __init__(self, *events, marshalls=None):
self.events = events
self.marshalls = dict()
if marshalls is not None:
# marshalls must be a list of callables that return True or False
self.marshalls['__general'] = marshalls
else
self.marshalls['__general'] = []
# event is a string with the name of the event you want to marshall
# or None if you want to marshall all of them
def register(self, callback, event=None):
if event = None:
self.marshalls['__general'].append(callback)
else:
self.marshalls.setdefault(event, list()).append(callback)
def run(self):
t=datetime(*datetime.now().timetuple()[:5])
while 1:
for e in self.events:
if all([x(e) for x in self.marshalls['__general']]) and
all([x(e) for x in self.marshalls[e.name]]):
# the above assumes e.name exists (not in reference implementation)
e.check(t)
t += timedelta(minutes=1)
while datetime.now() < t:
time.sleep((t - datetime.now()).seconds)
同じように、実行後のフックやその他の奇妙なものを必要に応じて追加できます。
イベントが消えるという質問に関して、問題をさらにトラブルシューティングできるように、コードをいくつか示してください。