時刻ちょうどに実行する その3
5秒に1回のタスクAと、15秒に1回のタスクBがある。
タスク自体は、マルチプロセスで動く。
タスクの実行中は、メインプロセスはある作業を実施できない。
タスクAまたはタスクBを実行した場合は、メインタスクを1回だけ実行する。
import multiprocessing import datetime import time class Worker(multiprocessing.Process): def __init__(self,t,workload=2): self.t=t self.workload=workload super(Worker, self).__init__() def run(self): #print(self.name,self.t) time.sleep(self.workload) return def uctdatetime00sec(pattern=None): """ 秒以下が0のdatetimeを返す。 pattern="future"の場合は、直近の未来の時刻を返す。 """ time_now=datetime.datetime.utcnow() if pattern=="future": time_offset=datetime.timedelta(minutes=1) # 1分先にずらしておく。 time_now=time_now + time_offset time_now=datetime.datetime(time_now.year, time_now.month, time_now.day, time_now.hour, time_now.minute, second=0, microsecond=0, tzinfo=None) return time_now if __name__ == '__main__': taskA=None taskB=None run_main_task=False #仮の時刻 time_now=datetime.datetime.utcnow() time_offset=datetime.timedelta(seconds=60) #繰り返しの間隔(秒) time_offset_taskA = datetime.timedelta(seconds=5) #繰り返しの間隔(秒) time_offset_taskB = datetime.timedelta(seconds=15) #繰り返しの間隔(秒) time_done_taskA=time_now time_done_taskB=time_now print(time_now) #0秒ちょうどの時刻から開始。 time_now=uctdatetime00sec(pattern="future") time_next_taskA=time_now + time_offset_taskA time_next_taskB=time_now + time_offset_taskB print("demo wills start at ", time_now) time_end=time_now + time_offset while time_end > datetime.datetime.utcnow():#デモプログラムなので1分で終わらせる。 time_now=datetime.datetime.utcnow() if time_now >= time_next_taskA: time_next_taskA=time_now + time_offset_taskA while time_now > time_next_taskA: print("skip taskA") time_next_taskA=time_now + time_offset_taskA #5秒に1回のタスクをここに記述(非同期) taskA=Worker(time_now,workload=1) # startは2回呼べないのでオブジェクトを作りなおし taskA.start() print("taskA start",time_now) run_main_task=True if time_now >= time_next_taskB: time_next_taskB=time_now + time_offset_taskB while time_now > time_next_taskB: print("skip taskB") time_next_taskB=time_now + time_offset_taskB time_next_taskB=time_now + time_offset_taskB #15秒に1回のタスクをここに記述(非同期) taskB=Worker(time_now,workload=1) # startは2回呼べないのでオブジェクトを作りなおし taskB.start() print("taskB start",time_now) run_main_task=True #全部のタスクが終わるのを待つ #動いていないタスクは待てない。。。 #ifの評価は左の論理が優先。 if (taskA is not None) and (taskA.is_alive()): taskA.join() if (taskB is not None) and (taskB.is_alive()): taskB.join() if run_main_task==True: print("main task",datetime.datetime.utcnow()) #変更後に1回メインタスクを実行したので次の変更まで何もしない。 run_main_task=False print("end")
実行結果
C:\>python C:\multiProcessTest2.py 2018-03-16 14:13:07.936899 demo wills start at 2018-03-16 14:14:00 taskA start 2018-03-16 14:14:05.000162 main task 2018-03-16 14:14:06.433244 taskA start 2018-03-16 14:14:10.000448 main task 2018-03-16 14:14:11.359526 taskA start 2018-03-16 14:14:15.000734 taskB start 2018-03-16 14:14:15.000734 main task 2018-03-16 14:14:16.387814 taskA start 2018-03-16 14:14:20.001020 main task 2018-03-16 14:14:21.356098 taskA start 2018-03-16 14:14:25.001306 main task 2018-03-16 14:14:26.358384 taskA start 2018-03-16 14:14:30.001592 taskB start 2018-03-16 14:14:30.001592 main task 2018-03-16 14:14:31.419673 taskA start 2018-03-16 14:14:35.001878 main task 2018-03-16 14:14:36.352956 taskA start 2018-03-16 14:14:40.002164 main task 2018-03-16 14:14:41.358242 taskA start 2018-03-16 14:14:45.002450 taskB start 2018-03-16 14:14:45.002450 main task 2018-03-16 14:14:46.407531 taskA start 2018-03-16 14:14:50.002736 main task 2018-03-16 14:14:51.363814 taskA start 2018-03-16 14:14:55.003022 main task 2018-03-16 14:14:56.368100 end