How do I run a scheduled job at random times daily starting with today? I want to use the schedule
package.
pip install schedule
import schedule
def job()
print("foo")
return schedule.CancelJob
while True:
time_str = '{:02d}:{:02d}'.format(random.randint(6, 10), random.randint(0, 59))
print("Scheduled for {}".format(time_str))
schedule.every().day.at(time_str).do(job)
schedule.run_pending()
The above code just spins:
Scheduled for 06:36
Scheduled for 10:00
Scheduled for 06:18
You're providing a moving target by putting your random time generator inside you while loop. Specifically, after reviewing the source code here, it is clear that the job will only run if datetime.datetime.now() >= self.next_run
is true (see scheduler.run_pending()
and job.should_run()
definitions). Because you are always moving job.next_run
, you will only hit it if it happens to be in the past on that particular iteration of the loop. Interestingly, I think this would cause a bug where the probability of actually running your job increases as you approach 24:00, though this has yet to be shown. I think you need to create a separate function for generating the next random time, and call it from your job function. For example:
import schedule
import time
import random
def job():
print("foo")
schedule_next_run()
return schedule.CancelJob
def schedule_next_run():
time_str = '{:02d}:{:02d}'.format(random.randint(6, 10), random.randint(0, 59))
schedule.clear()
print("Scheduled for {}".format(time_str))
schedule.every().day.at(time_str).do(job)
schedule_next_run()
while True:
schedule.run_pending()
time.sleep(60)
Note that the example may not be random for the day that the job starts, as your random time may be before the time you happen to start your script. You could work in a way to pick a random time in the future on the first day to circumvent this as needed.
To verify the above example, I used shorter time spans. The following works for me:
import schedule
import time
import random
def job():
print("foo")
schedule_next_run()
return schedule.CancelJob
def schedule_next_run():
time_span = random.randint(1, 5)
schedule.clear()
print(f'Scheduled in {time_span} seconds')
schedule.every(time_span).seconds.do(job)
schedule_next_run()
while True:
schedule.run_pending()