Verifying that an APScheduler task has properly executed - python

I'm trying to use the APScheduler library to execute a job at two certain times: 1am PST and 2am PST.
Sort of lost, I am trying to figure out what am doing wrong. Here is my code so far:
#!/usr/bin/python
import sys
import re
import urllib
import csv
import urllib2
import logging
import datetime
from apscheduler.schedulers.blocking import BlockingScheduler
sched = BlockingScheduler()
logging.basicConfig()
def main():
#Make a rest call, store the output in a csv, close the file.
...
f.close()
sched.add_job(my_job, 'date', run_date = '2015-12-15 01:00:00', args=['text'])
try:
sched.start()
print(datetime.datetime.now())
except (KeyboardInterrupt):
logger.debug('Terminating...')
print (datetime.datetime.now())
The current time is 12:16 PST, I just ran the above script and it executed and created the file prior to the job time of 12:30:30pm; this is for testing purposes.
So, I'm trying to figure out what I am doing wrong with regards to using APScheduler.
I want to improve this code, what are some things I can change?

If you want to run your code at certain times every time, you should be using the cron trigger:
sched.add_job(my_job, 'cron', hour='1,2', args=['text'])
For better debugging:
logging.basicConfig(level=logging.DEBUG)

Related

Python script scheduling [duplicate]

Before I ask, Cron Jobs and Task Scheduler will be my last options, this script will be used across Windows and Linux and I'd prefer to have a coded out method of doing this than leaving this to the end user to complete.
Is there a library for Python that I can use to schedule tasks? I will need to run a function once every hour, however, over time if I run a script once every hour and use .sleep, "once every hour" will run at a different part of the hour from the previous day due to the delay inherent to executing/running the script and/or function.
What is the best way to schedule a function to run at a specific time of day (more than once) without using a Cron Job or scheduling it with Task Scheduler?
Or if this is not possible, I would like your input as well.
AP Scheduler fit my needs exactly.
Version < 3.0
import datetime
import time
from apscheduler.scheduler import Scheduler
# Start the scheduler
sched = Scheduler()
sched.daemonic = False
sched.start()
def job_function():
print("Hello World")
print(datetime.datetime.now())
time.sleep(20)
# Schedules job_function to be run once each minute
sched.add_cron_job(job_function, minute='0-59')
out:
>Hello World
>2014-03-28 09:44:00.016.492
>Hello World
>2014-03-28 09:45:00.0.14110
Version > 3.0
(From Animesh Pandey's answer below)
from apscheduler.schedulers.blocking import BlockingScheduler
sched = BlockingScheduler()
#sched.scheduled_job('interval', seconds=10)
def timed_job():
print('This job is run every 10 seconds.')
#sched.scheduled_job('cron', day_of_week='mon-fri', hour=10)
def scheduled_job():
print('This job is run every weekday at 10am.')
sched.configure(options_from_ini_file)
sched.start()
Maybe this can help: Advanced Python Scheduler
Here's a small piece of code from their documentation:
from apscheduler.schedulers.blocking import BlockingScheduler
def some_job():
print "Decorated job"
scheduler = BlockingScheduler()
scheduler.add_job(some_job, 'interval', hours=1)
scheduler.start()
To run something every 10 minutes past the hour.
from datetime import datetime, timedelta
while 1:
print 'Run something..'
dt = datetime.now() + timedelta(hours=1)
dt = dt.replace(minute=10)
while datetime.now() < dt:
time.sleep(1)
For apscheduler < 3.0, see Unknown's answer.
For apscheduler > 3.0
from apscheduler.schedulers.blocking import BlockingScheduler
sched = BlockingScheduler()
#sched.scheduled_job('interval', seconds=10)
def timed_job():
print('This job is run every 10 seconds.')
#sched.scheduled_job('cron', day_of_week='mon-fri', hour=10)
def scheduled_job():
print('This job is run every weekday at 10am.')
sched.configure(options_from_ini_file)
sched.start()
Update:
apscheduler documentation.
This for apscheduler-3.3.1 on Python 3.6.2.
"""
Following configurations are set for the scheduler:
- a MongoDBJobStore named “mongo”
- an SQLAlchemyJobStore named “default” (using SQLite)
- a ThreadPoolExecutor named “default”, with a worker count of 20
- a ProcessPoolExecutor named “processpool”, with a worker count of 5
- UTC as the scheduler’s timezone
- coalescing turned off for new jobs by default
- a default maximum instance limit of 3 for new jobs
"""
from pytz import utc
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from apscheduler.executors.pool import ProcessPoolExecutor
"""
Method 1:
"""
jobstores = {
'mongo': {'type': 'mongodb'},
'default': SQLAlchemyJobStore(url='sqlite:///jobs.sqlite')
}
executors = {
'default': {'type': 'threadpool', 'max_workers': 20},
'processpool': ProcessPoolExecutor(max_workers=5)
}
job_defaults = {
'coalesce': False,
'max_instances': 3
}
"""
Method 2 (ini format):
"""
gconfig = {
'apscheduler.jobstores.mongo': {
'type': 'mongodb'
},
'apscheduler.jobstores.default': {
'type': 'sqlalchemy',
'url': 'sqlite:///jobs.sqlite'
},
'apscheduler.executors.default': {
'class': 'apscheduler.executors.pool:ThreadPoolExecutor',
'max_workers': '20'
},
'apscheduler.executors.processpool': {
'type': 'processpool',
'max_workers': '5'
},
'apscheduler.job_defaults.coalesce': 'false',
'apscheduler.job_defaults.max_instances': '3',
'apscheduler.timezone': 'UTC',
}
sched_method1 = BlockingScheduler() # uses overrides from Method1
sched_method2 = BlockingScheduler() # uses same overrides from Method2 but in an ini format
#sched_method1.scheduled_job('interval', seconds=10)
def timed_job():
print('This job is run every 10 seconds.')
#sched_method2.scheduled_job('cron', day_of_week='mon-fri', hour=10)
def scheduled_job():
print('This job is run every weekday at 10am.')
sched_method1.configure(jobstores=jobstores, executors=executors, job_defaults=job_defaults, timezone=utc)
sched_method1.start()
sched_method2.configure(gconfig=gconfig)
sched_method2.start()
the simplest option I can suggest is using the schedule library.
In your question, you said "I will need to run a function once every hour"
the code to do this is very simple:
import schedule
def thing_you_wanna_do():
...
...
return
schedule.every().hour.do(thing_you_wanna_do)
while True:
schedule.run_pending()
you also asked how to do something at a certain time of the day
some examples of how to do this are:
import schedule
def thing_you_wanna_do():
...
...
return
schedule.every().day.at("10:30").do(thing_you_wanna_do)
schedule.every().monday.do(thing_you_wanna_do)
schedule.every().wednesday.at("13:15").do(thing_you_wanna_do)
# If you would like some randomness / variation you could also do something like this
schedule.every(1).to(2).hours.do(thing_you_wanna_do)
while True:
schedule.run_pending()
90% of the code used is the example code of the schedule library. Happy scheduling!
Run the script every 15 minutes of the hour.
For example, you want to receive 15 minute stock price quotes, which are updated every 15 minutes.
while True:
print("Update data:", datetime.now())
sleep = 15 - datetime.now().minute % 15
if sleep == 15:
run_strategy()
time.sleep(sleep * 60)
else:
time.sleep(sleep * 60)
#For scheduling task execution
import schedule
import time
def job():
print("I'm working...")
schedule.every(1).minutes.do(job)
#schedule.every().hour.do(job)
#schedule.every().day.at("10:30").do(job)
#schedule.every(5).to(10).minutes.do(job)
#schedule.every().monday.do(job)
#schedule.every().wednesday.at("13:15").do(job)
#schedule.every().minute.at(":17").do(job)
while True:
schedule.run_pending()
time.sleep(1)
The Python standard library does provide sched and threading for this task. But this means your scheduler script will have be running all the time instead of leaving its execution to the OS, which may or may not be what you want.
On the version posted by sunshinekitty called "Version < 3.0" , you may need to specify apscheduler 2.1.2 . I accidentally had version 3 on my 2.7 install, so I went:
pip uninstall apscheduler
pip install apscheduler==2.1.2
It worked correctly after that. Hope that helps.
clock.py
from apscheduler.schedulers.blocking import BlockingScheduler
import pytz
sched = BlockingScheduler(timezone=pytz.timezone('Africa/Lagos'))
#sched.scheduled_job('cron', day_of_week='mon-sun', hour=22)
def scheduled_job():
print('This job is run every week at 10pm.')
#your job here
sched.start()
Procfile
clock: python clock.py
requirements.txt
APScheduler==3.0.0
After deployment, the final step is to scale up the clock process. This is a singleton process, meaning you’ll never need to scale up more than 1 of these processes. If you run two, the work will be duplicated.
$ heroku ps:scale clock=1
Source: https://devcenter.heroku.com/articles/clock-processes-python
Perhaps Rocketry suits your needs. It's a powerful scheduler that is very easy to use, has a lot of built-in scheduling options and it is easy to extend:
from rocketry import Rocketry
from rocketry.conds import daily, every, after_success
app = Rocketry()
#app.task(every("1 hour 30 minutes"))
def do_things():
...
#app.task(daily.between("12:00", "17:00"))
def do_daily_afternoon():
...
#app.task(daily & after_success(do_things))
def do_daily_after_task():
...
if __name__ == "__main__":
app.run()
It has much more though:
String based scheduling syntax
Logical statements (AND, OR, NOT)
A lot of built-in scheduling options
Easy to customize (custom conditions, parameters etc.)
Parallelization (run on separate thread or process)
Paramatrization (execution order and input-output)
Persistence: put the logs anywhere you like
Modify scheduler on runtime (ie. build API on top of it)
Links:
Documentation: https://rocketry.readthedocs.io/
Source code: https://github.com/Miksus/rocketry
Disclaimer: I'm the author
Probably you got the solution already #lukik, but if you wanna remove a scheduling, you should use:
job = scheduler.add_job(myfunc, 'interval', minutes=2)
job.remove()
or
scheduler.add_job(myfunc, 'interval', minutes=2, id='my_job_id')
scheduler.remove_job('my_job_id')
if you need to use a explicit job ID
For more information, you should check: https://apscheduler.readthedocs.io/en/stable/userguide.html#removing-jobs
I found that scheduler needs to run the program every second. If using a online server it would be costly.
So I have following:
It run at each minute at the 5th second, and you can change it to hours days by recalculating waiting period in seconds
import time
import datetime
Initiating = True
print(datetime.datetime.now())
while True:
if Initiating == True:
print("Initiate")
print( datetime.datetime.now())
time.sleep(60 - time.time() % 60+5)
Initiating = False
else:
time.sleep(60)
print("working")
print(datetime.datetime.now())
This method worked for me using relativedelta and datetime and a modulo boolean check for every hour.
It runs every hour from the time you start it.
import time
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
#Track next run outside loop and update the next run time within the loop
nxt_run=datetime.now()
#because while loops evaluate at microseconds we basically need to use a boolean evaluation to track when it should run next
while True:
cnow = datetime.now() #track the current time
time.sleep(1) #good to have so cpu doesn't spike
if (cnow.hour % 1 == 0 and cnow >= nxt_run):
print(f"start #{cnow}: next run #{nxt_run}")
nxt_run=cnow+relativedelta(hours=1) #add an hour to the next run
else:
print(f"next run #{nxt_run}")
One option is to write a C/C++ wrapper that executes the python script on a regular basis. Your end-user would run the C/C++ executable, which would remain running in the background, and periodically execute the python script. This may not be the best solution, and may not work if you don't know C/C++ or want to keep this 100% python. But it does seem like the most user-friendly approach, since people are used to clicking on executables. All of this assumes that python is installed on your end user's computer.
Another option is to use cron job/Task Scheduler but to put it in the installer as a script so your end user doesn't have to do it.

How to parse 100 json from wireshark?

I need to simulate one program 100 times, I need to have one simulation per hour (The duration of one simulation is 1 hour). From every simulation, I want to generate different json. My program must be stopped only be tapping 'exit' I try too to make that works:
from apscheduler.schedulers.blocking import BlockingScheduler
import os
def simulation():
os.system("./program")
print ("tshark -i tun0 -T ek > path/packets_one_hour.json")
scheduler = BlockingScheduler()
scheduler.add_job(some_job, 'interval', hours=1)
scheduler.start()
My problem is that my script is running without stopping. I can't generate 100 different json files. I must put quit after every hour in order to generate a new and different json. But I don't know how to do that.
Refering to this example from apscheduler docs, you could do the following.
from datetime import datetime
import os
import threading
from apscheduler.schedulers.blocking import BlockingScheduler
def json_dump():
# Put here your dump script
pass
def simulation():
os.system("./program")
t = threading.Timer(3600, json_dump)
t.start()
if __name__ == '__main__':
scheduler = BlockingScheduler()
scheduler.add_job(simulation, 'interval', hours=1, id='id_sim')
print('Press Ctrl+{0} to exit'.format('Break' if os.name == 'nt' else 'C'))
try:
scheduler.start()
except (KeyboardInterrupt, SystemExit):
pass
Honestly, haven't tried it. Let me know if it works.

django_apscheduler remove_all_jobs on django startup

I have used django_apscheduler to schedule jobs. And it's working fine. When I start server new job is added and periodically it's doing what I need to do. However if I exit django and start it again then django will fail with error.
apscheduler.jobstores.base.ConflictingIdError: u'Job identifier (myapp_db.jobs.test_job) conflicts with an existing job'
Basically old job exists in database and new job can not be created.
How can I remove all jobs during django startup.
I notice there is remove_all_job() function in apscheduler but I do not know from where to execute it?
I'm starting job.py from url.py with
import myapp.jobs
Thanks.
code:
import time
import sys
import requests
from bs4 import BeautifulSoup
import re
from kuce_db.models import NjuskaloData, UserVisitedData
import logging
from django.contrib.auth.models import User
from apscheduler.schedulers.background import BackgroundScheduler
from django_apscheduler.jobstores import DjangoJobStore, register_events, register_job
scheduler = BackgroundScheduler()
scheduler.add_jobstore(DjangoJobStore(), "default")
def get_trailing_number(s):
m = re.search(r'\d+$', s)
return int(m.group()) if m else None
#register_job(scheduler, "interval", seconds=300)
def test_job():
print("I'm a test job!")
register_events(scheduler)
#
scheduler.start()
print("Scheduler started!")
logging.basicConfig()
use replace_existing flag to tell it replace existed job
#register_job(scheduler, "interval", seconds=300, replace_existing=True)
def test_job():
print("I'm a test job!")

APscheduler will not stop

I have python code that I am developing for a website that, among other things, creates an excel sheet and then converts it into a json file. I need for this code to run continuously unless it is killed by the website administrator.
To this end, I am using APscheduler.
The code runs perfectly without APscheduler but when I attempt to add the rest of the code one of two things happens; 1) It runs forever and will not stop despite using "ctrl+C" and I need to stop it using task manager or 2) It only runs once, and then it stops
Code That doesn't Stop:
from apscheduler.scheduler import Scheduler
import logging
import time
logging.basicConfig()
sched = Scheduler()
sched.start()
(...)
code to make excel sheet and json file
(...)
#sched.interval_schedule(seconds = 15)
def job():
excelapi_final()
while True:
time.sleep(10)
sched.shutdown(wait=False)
Code that stops running after one time:
from apscheduler.scheduler import Scheduler
import logging
import time
logging.basicConfig()
sched = Scheduler()
(...)
#create excel sheet and json file
(...)
#sched.interval_schedule(seconds = 15)
def job():
excelapi_final()
sched.start()
while True:
time.sleep(10)
sched.shutdown(wait=False)
I understand from other questions, a few tutorials and the documentation that sched.shutdown should allow for the code to be killed by ctrl+C - however that is not working. Any ideas? Thanks in advance!
You could use the standalone mode:
sched = Scheduler(standalone=True)
and then start the scheduler like this:
try:
sched.start()
except (KeyboardInterrupt):
logger.debug('Got SIGTERM! Terminating...')
Your corrected code should look like this:
from apscheduler.scheduler import Scheduler
import logging
import time
logging.basicConfig()
sched = Scheduler(standalone=True)
(...)
code to make excel sheet and json file
(...)
#sched.interval_schedule(seconds = 15)
def job():
excelapi_final()
try:
sched.start()
except (KeyboardInterrupt):
logger.debug('Got SIGTERM! Terminating...')
This way the program will stop when Ctrl-C is pressed
You can gracefully shut it down:
import signal
from apscheduler.scheduler import Scheduler
import logging
import time
logging.basicConfig()
sched = Scheduler()
(...)
#create excel sheet and json file
(...)
#sched.interval_schedule(seconds = 15)
def job():
excelapi_final()
sched.start()
def gracefully_exit(signum, frame):
print('Stopping...')
sched.shutdown()
signal.signal(signal.SIGINT, gracefully_exit)
signal.signal(signal.SIGTERM, gracefully_exit)

Scheduling Python Script to run every hour accurately

Before I ask, Cron Jobs and Task Scheduler will be my last options, this script will be used across Windows and Linux and I'd prefer to have a coded out method of doing this than leaving this to the end user to complete.
Is there a library for Python that I can use to schedule tasks? I will need to run a function once every hour, however, over time if I run a script once every hour and use .sleep, "once every hour" will run at a different part of the hour from the previous day due to the delay inherent to executing/running the script and/or function.
What is the best way to schedule a function to run at a specific time of day (more than once) without using a Cron Job or scheduling it with Task Scheduler?
Or if this is not possible, I would like your input as well.
AP Scheduler fit my needs exactly.
Version < 3.0
import datetime
import time
from apscheduler.scheduler import Scheduler
# Start the scheduler
sched = Scheduler()
sched.daemonic = False
sched.start()
def job_function():
print("Hello World")
print(datetime.datetime.now())
time.sleep(20)
# Schedules job_function to be run once each minute
sched.add_cron_job(job_function, minute='0-59')
out:
>Hello World
>2014-03-28 09:44:00.016.492
>Hello World
>2014-03-28 09:45:00.0.14110
Version > 3.0
(From Animesh Pandey's answer below)
from apscheduler.schedulers.blocking import BlockingScheduler
sched = BlockingScheduler()
#sched.scheduled_job('interval', seconds=10)
def timed_job():
print('This job is run every 10 seconds.')
#sched.scheduled_job('cron', day_of_week='mon-fri', hour=10)
def scheduled_job():
print('This job is run every weekday at 10am.')
sched.configure(options_from_ini_file)
sched.start()
Maybe this can help: Advanced Python Scheduler
Here's a small piece of code from their documentation:
from apscheduler.schedulers.blocking import BlockingScheduler
def some_job():
print "Decorated job"
scheduler = BlockingScheduler()
scheduler.add_job(some_job, 'interval', hours=1)
scheduler.start()
To run something every 10 minutes past the hour.
from datetime import datetime, timedelta
while 1:
print 'Run something..'
dt = datetime.now() + timedelta(hours=1)
dt = dt.replace(minute=10)
while datetime.now() < dt:
time.sleep(1)
For apscheduler < 3.0, see Unknown's answer.
For apscheduler > 3.0
from apscheduler.schedulers.blocking import BlockingScheduler
sched = BlockingScheduler()
#sched.scheduled_job('interval', seconds=10)
def timed_job():
print('This job is run every 10 seconds.')
#sched.scheduled_job('cron', day_of_week='mon-fri', hour=10)
def scheduled_job():
print('This job is run every weekday at 10am.')
sched.configure(options_from_ini_file)
sched.start()
Update:
apscheduler documentation.
This for apscheduler-3.3.1 on Python 3.6.2.
"""
Following configurations are set for the scheduler:
- a MongoDBJobStore named “mongo”
- an SQLAlchemyJobStore named “default” (using SQLite)
- a ThreadPoolExecutor named “default”, with a worker count of 20
- a ProcessPoolExecutor named “processpool”, with a worker count of 5
- UTC as the scheduler’s timezone
- coalescing turned off for new jobs by default
- a default maximum instance limit of 3 for new jobs
"""
from pytz import utc
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from apscheduler.executors.pool import ProcessPoolExecutor
"""
Method 1:
"""
jobstores = {
'mongo': {'type': 'mongodb'},
'default': SQLAlchemyJobStore(url='sqlite:///jobs.sqlite')
}
executors = {
'default': {'type': 'threadpool', 'max_workers': 20},
'processpool': ProcessPoolExecutor(max_workers=5)
}
job_defaults = {
'coalesce': False,
'max_instances': 3
}
"""
Method 2 (ini format):
"""
gconfig = {
'apscheduler.jobstores.mongo': {
'type': 'mongodb'
},
'apscheduler.jobstores.default': {
'type': 'sqlalchemy',
'url': 'sqlite:///jobs.sqlite'
},
'apscheduler.executors.default': {
'class': 'apscheduler.executors.pool:ThreadPoolExecutor',
'max_workers': '20'
},
'apscheduler.executors.processpool': {
'type': 'processpool',
'max_workers': '5'
},
'apscheduler.job_defaults.coalesce': 'false',
'apscheduler.job_defaults.max_instances': '3',
'apscheduler.timezone': 'UTC',
}
sched_method1 = BlockingScheduler() # uses overrides from Method1
sched_method2 = BlockingScheduler() # uses same overrides from Method2 but in an ini format
#sched_method1.scheduled_job('interval', seconds=10)
def timed_job():
print('This job is run every 10 seconds.')
#sched_method2.scheduled_job('cron', day_of_week='mon-fri', hour=10)
def scheduled_job():
print('This job is run every weekday at 10am.')
sched_method1.configure(jobstores=jobstores, executors=executors, job_defaults=job_defaults, timezone=utc)
sched_method1.start()
sched_method2.configure(gconfig=gconfig)
sched_method2.start()
the simplest option I can suggest is using the schedule library.
In your question, you said "I will need to run a function once every hour"
the code to do this is very simple:
import schedule
def thing_you_wanna_do():
...
...
return
schedule.every().hour.do(thing_you_wanna_do)
while True:
schedule.run_pending()
you also asked how to do something at a certain time of the day
some examples of how to do this are:
import schedule
def thing_you_wanna_do():
...
...
return
schedule.every().day.at("10:30").do(thing_you_wanna_do)
schedule.every().monday.do(thing_you_wanna_do)
schedule.every().wednesday.at("13:15").do(thing_you_wanna_do)
# If you would like some randomness / variation you could also do something like this
schedule.every(1).to(2).hours.do(thing_you_wanna_do)
while True:
schedule.run_pending()
90% of the code used is the example code of the schedule library. Happy scheduling!
Run the script every 15 minutes of the hour.
For example, you want to receive 15 minute stock price quotes, which are updated every 15 minutes.
while True:
print("Update data:", datetime.now())
sleep = 15 - datetime.now().minute % 15
if sleep == 15:
run_strategy()
time.sleep(sleep * 60)
else:
time.sleep(sleep * 60)
#For scheduling task execution
import schedule
import time
def job():
print("I'm working...")
schedule.every(1).minutes.do(job)
#schedule.every().hour.do(job)
#schedule.every().day.at("10:30").do(job)
#schedule.every(5).to(10).minutes.do(job)
#schedule.every().monday.do(job)
#schedule.every().wednesday.at("13:15").do(job)
#schedule.every().minute.at(":17").do(job)
while True:
schedule.run_pending()
time.sleep(1)
The Python standard library does provide sched and threading for this task. But this means your scheduler script will have be running all the time instead of leaving its execution to the OS, which may or may not be what you want.
On the version posted by sunshinekitty called "Version < 3.0" , you may need to specify apscheduler 2.1.2 . I accidentally had version 3 on my 2.7 install, so I went:
pip uninstall apscheduler
pip install apscheduler==2.1.2
It worked correctly after that. Hope that helps.
clock.py
from apscheduler.schedulers.blocking import BlockingScheduler
import pytz
sched = BlockingScheduler(timezone=pytz.timezone('Africa/Lagos'))
#sched.scheduled_job('cron', day_of_week='mon-sun', hour=22)
def scheduled_job():
print('This job is run every week at 10pm.')
#your job here
sched.start()
Procfile
clock: python clock.py
requirements.txt
APScheduler==3.0.0
After deployment, the final step is to scale up the clock process. This is a singleton process, meaning you’ll never need to scale up more than 1 of these processes. If you run two, the work will be duplicated.
$ heroku ps:scale clock=1
Source: https://devcenter.heroku.com/articles/clock-processes-python
Perhaps Rocketry suits your needs. It's a powerful scheduler that is very easy to use, has a lot of built-in scheduling options and it is easy to extend:
from rocketry import Rocketry
from rocketry.conds import daily, every, after_success
app = Rocketry()
#app.task(every("1 hour 30 minutes"))
def do_things():
...
#app.task(daily.between("12:00", "17:00"))
def do_daily_afternoon():
...
#app.task(daily & after_success(do_things))
def do_daily_after_task():
...
if __name__ == "__main__":
app.run()
It has much more though:
String based scheduling syntax
Logical statements (AND, OR, NOT)
A lot of built-in scheduling options
Easy to customize (custom conditions, parameters etc.)
Parallelization (run on separate thread or process)
Paramatrization (execution order and input-output)
Persistence: put the logs anywhere you like
Modify scheduler on runtime (ie. build API on top of it)
Links:
Documentation: https://rocketry.readthedocs.io/
Source code: https://github.com/Miksus/rocketry
Disclaimer: I'm the author
Probably you got the solution already #lukik, but if you wanna remove a scheduling, you should use:
job = scheduler.add_job(myfunc, 'interval', minutes=2)
job.remove()
or
scheduler.add_job(myfunc, 'interval', minutes=2, id='my_job_id')
scheduler.remove_job('my_job_id')
if you need to use a explicit job ID
For more information, you should check: https://apscheduler.readthedocs.io/en/stable/userguide.html#removing-jobs
I found that scheduler needs to run the program every second. If using a online server it would be costly.
So I have following:
It run at each minute at the 5th second, and you can change it to hours days by recalculating waiting period in seconds
import time
import datetime
Initiating = True
print(datetime.datetime.now())
while True:
if Initiating == True:
print("Initiate")
print( datetime.datetime.now())
time.sleep(60 - time.time() % 60+5)
Initiating = False
else:
time.sleep(60)
print("working")
print(datetime.datetime.now())
This method worked for me using relativedelta and datetime and a modulo boolean check for every hour.
It runs every hour from the time you start it.
import time
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
#Track next run outside loop and update the next run time within the loop
nxt_run=datetime.now()
#because while loops evaluate at microseconds we basically need to use a boolean evaluation to track when it should run next
while True:
cnow = datetime.now() #track the current time
time.sleep(1) #good to have so cpu doesn't spike
if (cnow.hour % 1 == 0 and cnow >= nxt_run):
print(f"start #{cnow}: next run #{nxt_run}")
nxt_run=cnow+relativedelta(hours=1) #add an hour to the next run
else:
print(f"next run #{nxt_run}")
One option is to write a C/C++ wrapper that executes the python script on a regular basis. Your end-user would run the C/C++ executable, which would remain running in the background, and periodically execute the python script. This may not be the best solution, and may not work if you don't know C/C++ or want to keep this 100% python. But it does seem like the most user-friendly approach, since people are used to clicking on executables. All of this assumes that python is installed on your end user's computer.
Another option is to use cron job/Task Scheduler but to put it in the installer as a script so your end user doesn't have to do it.

Categories