UPDATED ANSWER (WORKING) -- 08-18-2022
As I previously stated I could not get @DialFrost recommendations in the other answer to work using Python 3.9 and APScheduler versions 3.9.x, 3.8.x, 3.7.x, 3.6.x and 3.5.x.
I decided to look at APScheduler 4.0.01a, which has been completely redesigned. BackgroundScheduler and BlockingScheduler were both removed in this new version.
Here is working code for Scheduler:
from datetime import datetime
from apscheduler.schedulers.sync import Scheduler
from apscheduler.triggers.interval import IntervalTrigger
first_run_time = datetime.now()
def periodic_extract_urls():
print(f'Extraction time: {datetime.now()}')
print(datetime.now() - first_run_time)
print('\n')
def periodic_check_urls():
print(f'Checking time: {datetime.now()}')
print(datetime.now() - first_run_time)
print('\n')
with Scheduler() as scheduler:
scheduler.add_schedule(func_or_task_id=periodic_extract_urls,
trigger=IntervalTrigger(minutes=15),
id="extract_urls")
scheduler.add_schedule(func_or_task_id=periodic_check_urls,
trigger=IntervalTrigger(minutes=5),
id="check_urls"
)
scheduler.wait_until_stopped()
This outputs this:
Extraction time: 2022-08-18 09:03:31.797858
0:00:00.009066
Checking time: 2022-08-18 09:03:31.797992
0:00:00.009181
Checking time: 2022-08-18 09:08:31.799883
0:05:00.011096
You can also use AsyncScheduler in APScheduler 4.0.01a.
from asyncio import run
from datetime import datetime, timedelta
from apscheduler.schedulers.async_ import AsyncScheduler
from apscheduler.triggers.interval import IntervalTrigger
first_run_time = datetime.now()
def periodic_extract_urls():
print(f'Extraction time: {datetime.now()}')
print(datetime.now() - first_run_time)
print('\n')
def periodic_check_urls():
print(f'Checking time: {datetime.now()}')
print(datetime.now() - first_run_time)
print('\n')
async def jobs():
async with AsyncScheduler() as scheduler:
await scheduler.add_schedule(func_or_task_id=periodic_extract_urls,
trigger=IntervalTrigger(minutes=15, start_time=first_run_time),
id="extract_urls"
)
await scheduler.add_schedule(func_or_task_id=periodic_check_urls,
trigger=IntervalTrigger(minutes=5,
start_time=first_run_time + timedelta(seconds=300)),
id="check_urls"
)
await scheduler.wait_until_stopped()
run(jobs())
Here is the output:
Extraction time: 2022-08-18 12:03:54.617456
0:00:00.015132
Checking time: 2022-08-18 12:08:54.615003
0:05:00.012665
Checking time: 2022-08-18 12:13:54.616444
0:10:00.014104
UPDATED ANSWER -- 08-17-2022
I have been trying to get misfire_grace_time to work with Python 3.9 and APScheduler versions 3.9.x, 3.8.x, 3.7.x, 3.6.x and 3.5.x.
I have also tried using coalesce and max_instances to solve the BackgroundScheduler issues. So far, nothing has worked and new errors have popped-up.
I looked at the APScheduler issues. I noted that this issue related to the BackgroundScheduler was raised in 2018 and is resolved in 4.0.1a And based on the released notes for 4.x, which is in alpha BackgroundScheduler is being replaced.
Repeating job with very short interval triggers exception on shutdown
I still recommend using BlockingScheduler either as an interval or as a cron.
Here is one of my old answers on using BlockingScheduler with cron
Here is the code that I'm currently testing with Python 3.9 and APScheduler versions 3.9.x, 3.8.x, 3.7.x, 3.6.x and 3.5.x.
from datetime import datetime, timedelta
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.executors.pool import ThreadPoolExecutor, ProcessPoolExecutor
executors = {
'default': ThreadPoolExecutor(20),
'processpool': ProcessPoolExecutor(5)
}
# 15*60
jobDefaults = {
'coalesce': True,
'max_instances': 100,
'misfire_grace_time': 15*60
}
scheduler = BackgroundScheduler(daemon=False, executors=executors, job_defaults=jobDefaults, timezone='UTC')
first_run_time = datetime.now()
def periodic_extract_urls():
print(f'Extraction time: {datetime.now()}')
print(datetime.now() - first_run_time)
def periodic_check_urls():
print(f'Checking time: {datetime.now()}')
print(datetime.now() - first_run_time)
def schedule_task():
print(f'Start time: {first_run_time}')
scheduler.add_job(func=periodic_extract_urls,
id="extract_urls",
trigger='interval',
minute=15,
next_run_time=first_run_time,
replace_existing=True,
)
scheduler.add_job(func=periodic_check_urls,
id="check_urls",
trigger='interval',
minute=5,
next_run_time=datetime.now() + timedelta(seconds=300),
replace_existing=True,
)
try:
scheduler.start()
print(scheduler.print_jobs())
except (KeyboardInterrupt, SystemExit):
print("shutdown scheduler")
scheduler.shutdown()
schedule_task()
ORIGINAL ANSWER -- 08-16-2022
I'm still trying to get the BackgroundScheduler to work correctly. I'm using Python 3.9, which required me to modify apscheduler util.py, which has a non-compliant time zone function for Python 3.9.
I was able to get something working using BlockingScheduler:
import logging
import datetime
from apscheduler.schedulers.blocking import BlockingScheduler
def periodic_extract_urls():
print(f'Extraction time: { datetime.datetime.now()}')
print(datetime.datetime.now() - first_run_time)
def periodic_check_urls():
print(f'Checking time: {datetime.datetime.now()}')
print(datetime.datetime.now() - first_run_time)
def schedule_task():
print(f'Start time: {first_run_time}')
scheduler.add_job(
periodic_extract_urls,
'interval',
minutes=15,
next_run_time=first_run_time
)
scheduler.add_job(
periodic_check_urls,
'interval',
minutes=5,
replace_existing=True,
next_run_time=datetime.datetime.now() + datetime.timedelta(seconds=300)
)
scheduler.start()
# run function
schedule_task()
This code output this:
Start time: 2022-08-16 15:19:12.727035
Extraction time: 2022-08-16 15:19:12.786244
0:00:00.059298
Checking time: 2022-08-16 15:24:12.796427
0:05:00.069420
Checking time: 2022-08-16 15:29:12.796830
0:10:00.069823
Extraction time: 2022-08-16 15:34:12.737923
0:15:00.010918
Checking time: 2022-08-16 15:34:12.790511
0:15:00.063520
Checking time: 2022-08-16 15:39:12.796448
0:20:00.069444
----------------------------------------
My system information
----------------------------------------
Platform: macOS
Python: 3.9.0
apscheduler: 3.9.1
----------------------------------------