简体   繁体   中英

Why does my scheduled task run exponentially after the first couple of times instead of at its scheduled intervals?

I'm working on a bot for Twitter that checks a users timeline at the same time every day and searches for a "Daily Tweet" from which to parse data, format it, and send it as a tweet from my bot.

Currently I've been using Pythons schedule module to read the users timeline at 6 different intervals (@ 1:19 min, 1:30 min, 2, 4, 10, and 20 minutes after 00:00 UTC) to see when and if that user has tweeted the "Daily Tweet" (which is usually tweeted within 5 minutes, but has gone as late as 20). While this method technically works as intended, I want to change the code so there is less of a delay between the time the user posts the daily tweet, and the time my bot responds to that tweet. Essentially, I want daemon-like behavior for an hour starting at a specific time every day.

schedule.every().day.at('19:01:19').do(daily_mode_inspector, False)  #
schedule.every().day.at('19:01:30').do(daily_mode_inspector, False)  #
schedule.every().day.at('19:02').do(daily_mode_inspector, False)  # at intervals, check for the daily change
schedule.every().day.at('19:04').do(daily_mode_inspector, False)  #
schedule.every().day.at('19:10').do(daily_mode_inspector, False)  #
schedule.every().day.at('19:20').do(daily_mode_inspector, True)  #

print('\nWaiting for next Daily Mode Inspection....')  

while True:

    schedule.run_pending()
    time.sleep(1)

What I recently tried is only having one daily scheduled task run right at 00:00 UTC and adding a line of code to the daily_mode_inspector function that runs every 10 seconds until a condition is met, then stops.

In testing what I was sure would be pretty straightforward code, I came across an issue where schedule.every(10).seconds.do(daily_mode_inspector) would produce some erratic behavior, in that it ran correctly the first two times (the first scheduled time, then 10 seconds after that), but at about the third run, it begins to start running exponentially, instead of linearly, if that makes any sense. To explain it better I tested it this way:

import datetime
import schedule
import pytz

def utc_stamp():

    utc_time = datetime.datetime.now(tz=pytz.UTC).strftime('%X')
    return utc_time


def daily_inspector():

    schedule.every(10).seconds.do(daily_inspector)
    print('Hello World', utc_stamp())


schedule.every().day.at('14:30').do(daily_inspector)

while True:

    schedule.run_pending()

Which produces these results:

Hello World 19:30:00
Hello World 19:30:10
Hello World 19:30:20
Hello World 19:30:20
Hello World 19:30:30
Hello World 19:30:30
Hello World 19:30:30
Hello World 19:30:30
Hello World 19:30:40
Hello World 19:30:40
Hello World 19:30:40
Hello World 19:30:40
Hello World 19:30:40
Hello World 19:30:40
Hello World 19:30:40

My expectation was that the code would run every 10 seconds, but instead what happens is that after the second run it will run the daily inspector code several times when it reaches the 10 seconds interval, and it only gets worse the longer the code runs. I'd like to know how I could make it so that it runs my function ever 10 seconds, without it leading to the nonsense above.

The reason is simply because you have created a recursive function, that is a function that calls itself.

To fix it, isolate the routine to be performed from the call to perform it.

Update daily_inspector() as follows:

def daily_inspector():
    schedule.every(10).seconds.do(do_routine)

Then define do_routine as follows:

def do_routine():
    print('Hello World', utc_stamp())

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM