I made the following ,but it doesn't print the time.
from apscheduler.schedulers.background import BackgroundScheduler
from datetime import datetime
def tick():
print('Tick! The time is: %s' % datetime.now())
scheduler = BackgroundScheduler()
scheduler.add_job(tick,'interval',seconds=3)
print('starting')
scheduler.start()
print('stopped')
This is because your program is exiting before the interval has elapsed and needs to be kept alive at least until the first interval, consider using the following example:
while True:
#Thread activity here (time.sleep(2) for example)
or using other forms of activity to keep your main thread alive. Or just print out the time without this scheduling if that's what you really need.
Related
I am running the below code as an example where the function gets data and cleans it and shows the result every five minutes.
import schedule
import time
def job():
print("I'm working...")
schedule.every(5).minutes.do(job)
while True:
schedule.run_pending()
time.sleep(1)
The problem I have now is when the function runs, it takes a few seconds to do everything. For example, if the code runs at 9:00 am, it takes 2-5 seconds to complete the task. Due to this, the next time code runs at 9:05:05 seconds.
Is there a solution that can help me run the function every 5 minutes even after taking some time to complete the tasks in the function? I want the function to run exactly at 9:00 am, 9:05 am, and 9:10 am respectively.
Run another thread as mentioned in schedule docs: https://schedule.readthedocs.io/en/stable/
Schedule does not account for the time it takes for the job function to execute. To guarantee a stable execution schedule you need to move long-running jobs off the main-thread (where the scheduler runs). See Parallel execution for a sample implementation.
and once again I copy from documentation:
import threading
import time
import schedule
def job():
print("I'm running on thread %s" % threading.current_thread())
def run_threaded(job_func):
job_thread = threading.Thread(target=job_func)
job_thread.start()
schedule.every(10).seconds.do(run_threaded, job)
schedule.every(10).seconds.do(run_threaded, job)
schedule.every(10).seconds.do(run_threaded, job)
schedule.every(10).seconds.do(run_threaded, job)
schedule.every(10).seconds.do(run_threaded, job)
while 1:
schedule.run_pending()
time.sleep(1)
I already searched and see many people are with problems because the schedule doesn't control the execution time, and the workaround for this is the Parallel execution: here
Even after trying this, I still have the problem and even missed one call on date: 2023-02-15 21:03:11
Current Time = 2023-02-15 21:03:09.996591 <Thread(Thread-196 (test), started 123145329221632)>
Current Time = 2023-02-15 21:03:10.999913 <Thread(Thread-197 (test), started 123145329221632)>
Current Time = 2023-02-15 21:03:12.000702 <Thread(Thread-198 (test), started 123145329221632)>
Current Time = 2023-02-15 21:03:13.002731 <Thread(Thread-199 (test), started 123145329221632)>
Can someone help me with this? I would appreciate it so much.
my code:
import time
from datetime import datetime, timedelta
import threading
def test():
current_time = datetime.now()
print("Current Time =", current_time, threading.current_thread())
def run_threaded(job_func):
job_thread = threading.Thread(target=job_func)
job_thread.start()
schedule.every(1).seconds.do(run_threaded, test)
if __name__ == "__main__":
while True:
schedule.run_pending()
time.sleep(1)
When I click the arrow to run the python code, it simply executes.
However, if I select the option to run the code line-by-line, then the scheduled tasks will continually run as desired.
import datetime
from datetime import datetime, timedelta
import time
from apscheduler.schedulers.background import BackgroundScheduler
sched = BackgroundScheduler(daemon=True)
frequency = 10/60
def main_func(frequency):
start_time = datetime.now()
end_time = start_time + timedelta(minutes=frequency)
print("Start Time: ", start_time)
print("End Time: ", end_time)
if __name__ == "__main__":
sched.add_job(main_func, 'interval', [frequency], minutes=frequency)
sched.start()
(Undesired): Pressing Button in VSCode:
(Desired): Selecting All Code in script within VSCode, Right Clicking and Run Line-by-Line
Questions:
How can I run the python file so it behaves like I ran it line-by-line and doesn't immediately terminate?
Also, will that method work if I ran the python script from a task scheduler?
The answer to this question is is literally the first entry in the APScheduler FAQ.
The essence is that you're starting a background service and then letting the script run to the end which then exits the process. Use cases like these are what BlockingScheduler is for:
from datetime import datetime, timedelta
import time
from apscheduler.schedulers.blocking import BlockingScheduler
sched = BlockingScheduler()
frequency = 10/60
def main_func(frequency):
start_time = datetime.now()
end_time = start_time + timedelta(minutes=frequency)
print("Start Time: ", start_time)
print("End Time: ", end_time)
if __name__ == "__main__":
sched.add_job(main_func, 'interval', [frequency], minutes=frequency)
sched.start()
The job_function isnt getting executed even once, even when i waited for more than 10 mins.
from apscheduler.schedulers.background import BackgroundScheduler
import send_mail
def job_function():
print("Hello World")
send_mail('abc#test.com')
sched = BackgroundScheduler()
sched.add_job(job_function, 'interval', minutes=1)
sched.start()
Based on this code, and this code only, the problem looks like that your program terminates before the time limit is reached.
Try adding this infinite loop at the end of your program which will prevent it to quit:
while True:
time.sleep(1000)
Then terminate your program with CTRL+C.
Using python's schedule module how can I start a job at particular time and thereon it should be scheduled at regular intervals.
Suppose I want to schedule a task every 4 hours starting from 09:00 am.
schedule.every(4).hours.at("09:00").do(task) # This doesn't work
How to achieve the above?
You can convert the inner schedule (every 4 hours) into a separate function which would be called by the main schedule (fixed time). The inner schedule function would be the one calling your job function.
Example -
import schedule
import time
def job():
print "I am working" #your job function
def schedule_every_four_hours():
job() #for the first job to run
schedule.every(4).hour.do(job)
return schedule.CancelJob
schedule.every().day.at("09:00").do(schedule_every_four_hours)
while True:
schedule.run_pending()
time.sleep(1)
If you would like to kill the schedule based on your requirement read more here. Check here.
The above solution will not work if there are multiple schedules, as the schedule.CancelJob will cancel the other schedules on the pipe, better to use clear tag
import schedule
from datetime import datetime
import time
def task():
print 'I am here...',datetime.now()
def schedule_every_four_hours(clear):
if clear =='clear':
schedule.every(2).seconds.do(task).tag('mytask1') #for the first job to runschedule.every(4).hour.at("9:00").do(task)
else:
schedule.every(5).seconds.do(task).tag('mytask2') # for the second job to runschedule.every(4).hour.at("9:00").do(task)
print clear
schedule.clear(clear)
now = datetime.now()
times = str(now.hour+0)+ ":"+str(now.minute+1)
times1 = str(now.hour+0)+ ":"+str(now.minute+3)
schedule.every().day.at(times).do(schedule_every_four_hours,'clear').tag('clear')
schedule.every().day.at(times1).do(schedule_every_four_hours,'clear1').tag('clear1')
while True:
schedule.run_pending()
time.sleep(1)
Just as add on - because I was searching for a solution for this:
Start at a specific time
Have an interval
Exit at a specific time
import schedule
import time
from datetime import datetime as dt
def job():
now = dt.now()
dt_string = now.strftime('%Y-%m-%d %H:%M:%S')
print ("I am working " ,dt_string )#your job function
def schedule_every_four_hours():
job() #for the first job to run
schedule.every(2).minutes.until("09:46").do(job)
print(' 2 Minuten')
return schedule.CancelJob
schedule.every().day.at("09:29").do(schedule_every_four_hours)
while True:
schedule.run_pending()
time.sleep(1)
I am using python apscheduler to schedule a specific task every 45 minutes. The problem is, when i add the job and start the scheduler, it starts at 45 minutes from now.
from apscheduler.schedulers.blocking import BlockingScheduler
class myClass:
def schedule(self):
self.scheduler = BlockingScheduler()
self.scheduler.add_job(self.myJob, 'interval', minutes=45)
self.scheduler.start()
def myJob(self):
print('I finally started')
I tried setting start_date, but with no success. How can i make sure the job is executed immediately, and not after waiting the interval for the first time?
Try next_run_time=datetime.now().
Not a good solution but works for me.
from apscheduler.schedulers.blocking import BlockingScheduler
class myClass:
def schedule(self):
self.myJob()#run your job immediately here, then scheduler
self.scheduler = BlockingScheduler()
self.scheduler.add_job(self.myJob, 'interval', minutes=45)
self.scheduler.start()
def myJob(self):
print('I finally started')
The given answers are too complex for a simple task that is well documented:
https://apscheduler.readthedocs.io/en/3.x/modules/triggers/date.html#examples
To add a job to be run immediately:
The 'date' trigger and datetime.now() as run_date are implicit
sched.add_job(my_job)