タイトルの通りです。
基本的に繰り返し処理を書くと、処理の重さによって次の処理の開始が遅くなっていきます。
基本1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import time import datetime as dt
while True: start_datetime = dt.datetime.now() print(f'START: {start_datetime}')
''' 何か処理 '''
time.sleep(10) pass
# START: 2021-12-18 21:09:57.488152 # START: 2021-12-18 21:10:07.492113 # START: 2021-12-18 21:10:17.508288 # START: 2021-12-18 21:10:27.515364 # START: 2021-12-18 21:10:37.525368 # START: 2021-12-18 21:10:47.541210 # START: 2021-12-18 21:10:57.555242
|
何も対策を入れないと1ループで20ミリ秒遅れていきます。なので1日動かすと約3秒ズレることになり、これはゆゆしき問題です。
基本2
もし上記の繰り返しで重たい処理をしたらどうなるでしょう?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import time import datetime as dt
def slow_process(): trash = 1 for idx in range(10000000): trash = trash * idx pass pass
while True: start_datetime = dt.datetime.now() print(f'START: {start_datetime}')
''' 何か重たい処理 ''' slow_process()
time.sleep(10) pass
# START: 2021-12-18 21:24:35.974505 # START: 2021-12-18 21:24:46.887488 # START: 2021-12-18 21:24:57.797534 # START: 2021-12-18 21:25:08.712103 # START: 2021-12-18 21:25:19.625054 # START: 2021-12-18 21:25:30.562727 # START: 2021-12-18 21:25:41.477604
|
このように1回のループで1秒ずつ遅れていきます。常に動かす必要がある処理だと、何か対策を入れないといけません。
対策
今回の問題は処理に時間がかかったにもかかわらず、スリープが10秒の固定なのが問題です。
処理にかかった時間を差し引いて、 スリープ時間を調整してあげれば常に一定で繰り返しさせることができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| import time import datetime as dt
def slow_process(): trash = 1 for idx in range(10000000): trash = trash * idx pass pass
while True: start_datetime = dt.datetime.now() print(f'START: {start_datetime}')
''' 何か重たい処理 ''' slow_process()
now_datetime = dt.datetime.now() next_datetime = start_datetime + dt.timedelta(seconds=10) next_seconds = (next_datetime - now_datetime).seconds # print(f"sleep: {next_seconds}sec") time.sleep(next_seconds) pass
# START: 2021-12-18 21:39:32.871239 # START: 2021-12-18 21:39:42.793268 # START: 2021-12-18 21:39:52.698554 # START: 2021-12-18 21:40:02.608381 # START: 2021-12-18 21:40:12.530488 # START: 2021-12-18 21:40:22.452134 # START: 2021-12-18 21:40:32.387661
|
このように、処理の開始時間と処理が終わった時間を差し引いて、スリープ時間を算出するようにすると、いくら重い処理をしても時間がズレることがなくなります。