How to get VSCode to run an apscheduler without terminating? - python

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()

Related

python schedule running every 5 minutes adds few seconds delay

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)

python apscheduler does nothing

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.

How to import a python file to be executed on schedule time. using schedule

I am trying to use schedule to schedule jobs every work day at a certain time and execute a file when its time. The problem is that it runs the validate.py on schedule and off schedule. I want it to run only when the time is 9:09 .
from dateutil import rrule
from datetime import datetime, timedelta
import time
import schedule
import requests
import validate.py
def job():
execfile("validate.py")
start_hour = datetime.strptime("09:09:26","%H:%M:%S")
end_hour = start_hour + timedelta(hours=7)
for t in rrule.rrule(rrule.HOURLY, dtstart=start_hour, until=end_hour):
schedule.every().monday.at(t.strftime("%H:%M")).do(job)
schedule.every().tuesday.at(t.strftime("%H:%M")).do(job)
schedule.every().wednesday.at(t.strftime("%H:%M")).do(job)
schedule.every().thursday.at(t.strftime("%H:%M")).do(job)
schedule.every().friday.at(t.strftime("%H:%M")).do(job)
while True:
schedule.run_pending()
time.sleep(1)
import pytz
from apscheduler.schedulers.blocking import BlockingScheduler
def job():
execfile("validate.py")
if __name__ == '__main__':
timez = pytz.timezone(YOUR_TIMEZONE)
scheduler = BlockingScheduler(timezone=timez)
scheduler.add_job(job, "cron", day_of_week="1-5", hour=9, minute=9)
scheduler.start()
BlockingScheduler might be useful on your case. the parameter: YOUR_TIMEZONE just like'Asia/Shanghai'

How to stop/terminate a python script from running with BackgroundScheduler() of APScheduler

I'm trying to stop the while loop execution from inside the foo() function. I've tried exit() / sys.exit without success. How can I stop completely the execution of the program from inside the function?
from apscheduler.schedulers.background import BackgroundScheduler
from datetime import datetime, timedelta
import time
import sys
def foo(stop = False):
print('Function foo executed')
if stop:
sys.exit
scheduler = BackgroundScheduler()
dd = datetime.now() + timedelta(seconds=10)
scheduler.add_job(foo, 'date', run_date=dd, args=[True])
scheduler.start()
while True:
print('Inside the loop')
time.sleep(2)
Use psutil
import psutil
psutil.Process().terminate()
From the doc,
psutil.Process() If PID is omitted current process PID (os.getpid()) is used.
Be aware terminate will leave with exit code 0. If you want other exit code, you can use send_signal() or even kill()

How to schedule job with a particular time as well as interval?

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)

Categories

Resources