CrazyCoder
CrazyCoder

Reputation: 2388

Schedule calculation exactly at every 15 mins using Python

I have followed the example which is shown here.

It is working as expected, but with a small problem. If the do_job() method takes more than a minute to finish. It's waiting for another 1 min from end of the do_job() method and scheduling another calculation.

But I want it to start timings 1 min from the start of execution time. Is there a possibility to do that?

EDIT

import schedule
import time

def job():
    print("Process triggered at:", time.strftime("%Y-%m-%d %H:%M:%S"))
    time.sleep(30)
    print("Process ended at:", time.strftime("%Y-%m-%d %H:%M:%S"))

# Define the frequency (in seconds) at which the process should be triggered
frequency_seconds = 60  # Trigger every 60 seconds

# Schedule the job to run at the specified frequency
schedule.every(frequency_seconds).seconds.do(job)

# Main loop to keep the script running
while True:
    schedule.run_pending()
    time.sleep(1)  # Sleep for 1 second to avoid high CPU usage

In the above code , the output generated is as below :

Process triggered at: 2024-03-25 06:57:23
Process ended at: 2024-03-25 06:57:53
Process triggered at: 2024-03-25 06:58:54
Process ended at: 2024-03-25 06:59:24

It is observed that the next process is triggered after the first process has ended. The time difference between first process end time and second process start time is 60 seconds.

But my expectation is the time difference between first process trigger time and second process trigger time should be 60 seconds. 60 seconds should not be calculation from process end time. job() should be called exactly at 60 seconds interval. So the expected output will look like this :

Process triggered at: 2024-03-25 06:57:23
Process ended at: 2024-03-25 06:57:53
Process triggered at: 2024-03-25 06:58:23
Process ended at: 2024-03-25 06:58:53

Upvotes: 0

Views: 211

Answers (2)

101
101

Reputation: 8999

The timed-count package makes that pretty simple.

It won't suffer from lag over time, and it can also optionally raise an error if your job takes too long.

from timed_count import timed_count

for _ in timed_count(period=60, error_on_missed=True):
    job()

Upvotes: 1

Mark Setchell
Mark Setchell

Reputation: 207778

If your objective is to start jobs a given number of seconds since the start of the previous job rather than since the end of the previous job, you can use the following code:

#!/usr/bin/env python3

import sched, time

# Define the frequency (in seconds) at which the process should be triggered
frequency_seconds = 60  # Trigger every 60 seconds
priority = 1

# Create a scheduler
s = sched.scheduler(time.time, time.sleep)

def job():
    # Reschedule ourselves for next run
    s.enterabs(time.time() + frequency_seconds, priority, job)

    print("Process triggered at:", time.strftime("%Y-%m-%d %H:%M:%S"))
    time.sleep(25)
    print("Process ended at:", time.strftime("%Y-%m-%d %H:%M:%S"))

# Start first job immediately, i.e. delay=0
s.enter(0, priority, job)

# Keep running future jobs
s.run()

If your concern is that new jobs cannot be started while previous jobs are still running. i.e. that you want to start new jobs every minute even if they take 90 seconds to run, you may have to use threads. Please say if that is the issue.

Upvotes: 1

Related Questions