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