処理が重くても指定時間後に再試行する処理

アプリ開発

タイトルの通りです。

基本的に繰り返し処理を書くと、処理の重さによって次の処理の開始が遅くなっていきます。

スポンサーリンク

基本1

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

もし上記の繰り返しで重たい処理をしたらどうなるでしょう?

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秒の固定なのが問題です。

処理にかかった時間を差し引いて、 スリープ時間を調整してあげれば常に一定で繰り返しさせることができます。

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

このように、処理の開始時間と処理が終わった時間を差し引いて、スリープ時間を算出するようにすると、いくら重い処理をしても時間がズレることがなくなります。

タイトルとURLをコピーしました