Advanced Python Scheduler (APScheduler)
raw JSON → 3.11.2 verified Tue May 12 auth: no python install: verified
APScheduler is a flexible, in-process task scheduler library for Python, offering cron-like capabilities. It allows you to schedule Python code to be executed later, either once or periodically, within your application. The current stable version is 3.11.2. It supports various scheduler types, job stores (e.g., in-memory, SQLAlchemy, MongoDB), and triggers (date, interval, cron, calendarinterval). APScheduler is primarily meant to be run inside existing applications, not as a standalone daemon. It is actively maintained with a stable 3.x series and an ongoing pre-release 4.x series with significant architectural changes.
pip install apscheduler Common errors
error ImportError: cannot import name 'AsyncIOSchedular' ↓
cause The class name 'AsyncIOSchedular' is misspelled; the correct spelling is 'AsyncIOScheduler'.
fix
from apscheduler.schedulers.asyncio import AsyncIOScheduler
error AttributeError: module 'apscheduler.schedulers.asyncio' has no attribute 'get_event_loop' ↓
cause The 'asyncio' module from APScheduler is being imported instead of Python's standard 'asyncio' module.
fix
import asyncio
error ImportError: cannot import name 'monthrange' ↓
cause A local file named 'calendar.py' is shadowing Python's standard 'calendar' module.
fix
Rename the local 'calendar.py' file to avoid name conflicts.
error ModuleNotFoundError: No module named 'apscheduler' ↓
cause The APScheduler library is either not installed, installed in a different Python environment than the one being used, or there's a naming conflict with a local file named 'apscheduler.py'.
fix
Ensure APScheduler is installed in your current Python environment using
pip install apscheduler. If using a virtual environment, activate it before installing. If a local file apscheduler.py exists, rename it. error ValueError: This Job cannot be serialized since the reference to its callable (<bound method xxxxxxxx.on_crn_field_submission of <__main__.xxxxxxx object at xxxxxxxxxxxxx>>) could not be determined. Consider giving a textual reference (module:function name) instead. ↓
cause This error occurs when trying to schedule a function that cannot be reliably serialized (e.g., lambda functions, bound methods, nested functions) which is required by persistent job stores or process pool executors for job persistence or inter-process communication.
fix
Define the job function as a module-level function, a static method, or a class method. Pass a textual reference (e.g., 'your_module.your_function') instead of a direct callable reference to
add_job. Warnings
breaking APScheduler 4.0 (currently in pre-release) introduces significant breaking changes. Key changes include a split of the 'job' concept into 'Task', 'Schedule', and 'Job', the merging of 'workers' into 'schedulers', removal of synchronous interfaces for event brokers and data stores, and a completely overhauled job store system that is incompatible with 3.x data. The `add_job()` method is renamed to `add_schedule()`. ↓
fix Refer to the APScheduler 4.x migration guide before upgrading. A direct migration path for persistent job store data from 3.x to 4.x is not automatically available at the time of writing and may require manual recreation or a specific migration tool when 4.x is stable.
gotcha When using `BackgroundScheduler`, if your main script finishes, the scheduler will also stop. You need to keep the main thread alive (e.g., with `time.sleep()`, a web server, or another blocking call) for the background jobs to execute. ↓
fix For standalone scripts, use `while True: time.sleep(interval)` with a `try...except KeyboardInterrupt` block, or use `BlockingScheduler` if the scheduler is the only thing running in your process. For web applications, ensure the scheduler's lifecycle is tied to the application's.
gotcha Functions scheduled with persistent job stores (e.g., SQLAlchemyJobStore, MongoDBJobStore) must be importable by a textual reference (e.g., 'mymodule:my_function'). Lambda functions, bound methods, or nested functions often cannot be properly serialized and deserialized across application restarts or different processes, leading to `ValueError`. ↓
fix Ensure scheduled functions are top-level functions in a module, or static/class methods, and provide their fully qualified path (e.g., `scheduler.add_job('my_module.my_function', ...)`).
gotcha Sharing a persistent job store among multiple APScheduler *instances* (in different processes or nodes) directly can lead to incorrect behavior like duplicate job execution or missed jobs, as APScheduler 3.x does not have built-in interprocess synchronization for job stores. ↓
fix For multi-process or multi-node deployments, APScheduler 3.x typically requires a single, dedicated scheduler process that manages jobs, with other processes communicating with it. Alternatively, consider using a distributed task queue (like Celery) if strong guarantees and distributed coordination are critical. APScheduler 4.x aims to address this with enhanced data stores and event brokers.
deprecated Support for `pytz` time zones has been deprecated in version 3.11.0 in favor of `zoneinfo` (or `backports.zoneinfo` for Python < 3.9). ↓
fix Migrate your timezone definitions to use `zoneinfo` (built-in in Python 3.9+) or `backports.zoneinfo` for older Python versions. For example, `from zoneinfo import ZoneInfo` instead of `from pytz import timezone`.
Install
pip install apscheduler[sqlalchemy] pip install apscheduler[mongodb] pip install apscheduler[redis] pip install apscheduler[asyncpg] Install compatibility verified last tested: 2026-05-12
python os / libc variant status wheel install import disk
3.10 alpine (musl) apscheduler wheel - 0.26s 18.5M
3.10 alpine (musl) apscheduler - - 0.28s 18.5M
3.10 alpine (musl) asyncpg wheel - 0.28s 18.5M
3.10 alpine (musl) asyncpg - - 0.29s 18.5M
3.10 alpine (musl) mongodb sdist - 0.24s 26.6M
3.10 alpine (musl) mongodb - - 0.24s 26.5M
3.10 alpine (musl) redis wheel - 0.29s 22.3M
3.10 alpine (musl) redis - - 0.28s 22.3M
3.10 alpine (musl) sqlalchemy wheel - 0.27s 43.2M
3.10 alpine (musl) sqlalchemy - - 0.28s 43.2M
3.10 slim (glibc) apscheduler wheel 1.7s 0.20s 19M
3.10 slim (glibc) apscheduler - - 0.18s 19M
3.10 slim (glibc) asyncpg wheel 1.6s 0.19s 19M
3.10 slim (glibc) asyncpg - - 0.18s 19M
3.10 slim (glibc) mongodb wheel 2.8s 0.18s 29M
3.10 slim (glibc) mongodb - - 0.18s 28M
3.10 slim (glibc) redis wheel 1.9s 0.19s 23M
3.10 slim (glibc) redis - - 0.18s 23M
3.10 slim (glibc) sqlalchemy wheel 3.4s 0.19s 42M
3.10 slim (glibc) sqlalchemy - - 0.19s 42M
3.11 alpine (musl) apscheduler wheel - 0.38s 20.4M
3.11 alpine (musl) apscheduler - - 0.39s 20.4M
3.11 alpine (musl) asyncpg wheel - 0.37s 20.4M
3.11 alpine (musl) asyncpg - - 0.39s 20.4M
3.11 alpine (musl) mongodb sdist - 0.33s 30.0M
3.11 alpine (musl) mongodb - - 0.36s 29.9M
3.11 alpine (musl) redis wheel - 0.36s 25.0M
3.11 alpine (musl) redis - - 0.40s 25.0M
3.11 alpine (musl) sqlalchemy wheel - 0.35s 48.4M
3.11 alpine (musl) sqlalchemy - - 0.40s 48.3M
3.11 slim (glibc) apscheduler wheel 1.7s 0.31s 21M
3.11 slim (glibc) apscheduler - - 0.29s 21M
3.11 slim (glibc) asyncpg wheel 1.7s 0.32s 21M
3.11 slim (glibc) asyncpg - - 0.30s 21M
3.11 slim (glibc) mongodb wheel 2.6s 0.31s 33M
3.11 slim (glibc) mongodb - - 0.29s 33M
3.11 slim (glibc) redis wheel 2.1s 0.33s 25M
3.11 slim (glibc) redis - - 0.29s 25M
3.11 slim (glibc) sqlalchemy wheel 3.1s 0.33s 47M
3.11 slim (glibc) sqlalchemy - - 0.29s 47M
3.12 alpine (musl) apscheduler wheel - 0.60s 12.3M
3.12 alpine (musl) apscheduler - - 0.58s 12.3M
3.12 alpine (musl) asyncpg wheel - 0.56s 12.3M
3.12 alpine (musl) asyncpg - - 0.57s 12.3M
3.12 alpine (musl) mongodb sdist - 0.60s 21.6M
3.12 alpine (musl) mongodb - - 0.57s 21.5M
3.12 alpine (musl) redis wheel - 0.55s 16.7M
3.12 alpine (musl) redis - - 0.58s 16.7M
3.12 alpine (musl) sqlalchemy wheel - 0.58s 39.7M
3.12 alpine (musl) sqlalchemy - - 0.58s 39.7M
3.12 slim (glibc) apscheduler wheel 1.6s 0.56s 13M
3.12 slim (glibc) apscheduler - - 0.52s 13M
3.12 slim (glibc) asyncpg wheel 1.5s 0.52s 13M
3.12 slim (glibc) asyncpg - - 0.53s 13M
3.12 slim (glibc) mongodb wheel 2.4s 0.52s 25M
3.12 slim (glibc) mongodb - - 0.53s 25M
3.12 slim (glibc) redis wheel 1.8s 0.52s 17M
3.12 slim (glibc) redis - - 0.53s 17M
3.12 slim (glibc) sqlalchemy wheel 2.9s 0.55s 38M
3.12 slim (glibc) sqlalchemy - - 0.53s 38M
3.13 alpine (musl) apscheduler wheel - 0.59s 12.0M
3.13 alpine (musl) apscheduler - - 0.59s 11.9M
3.13 alpine (musl) asyncpg wheel - 0.57s 12.0M
3.13 alpine (musl) asyncpg - - 0.58s 11.9M
3.13 alpine (musl) mongodb sdist - 0.58s 21.3M
3.13 alpine (musl) mongodb - - 0.56s 21.1M
3.13 alpine (musl) redis wheel - 0.66s 16.4M
3.13 alpine (musl) redis - - 0.60s 16.3M
3.13 alpine (musl) sqlalchemy wheel - 0.57s 39.2M
3.13 alpine (musl) sqlalchemy - - 0.59s 39.1M
3.13 slim (glibc) apscheduler wheel 1.5s 0.53s 13M
3.13 slim (glibc) apscheduler - - 0.54s 12M
3.13 slim (glibc) asyncpg wheel 1.5s 0.53s 13M
3.13 slim (glibc) asyncpg - - 0.54s 12M
3.13 slim (glibc) mongodb wheel 2.4s 0.51s 26M
3.13 slim (glibc) mongodb - - 0.56s 25M
3.13 slim (glibc) redis wheel 1.9s 0.52s 17M
3.13 slim (glibc) redis - - 0.55s 17M
3.13 slim (glibc) sqlalchemy wheel 3.0s 0.52s 38M
3.13 slim (glibc) sqlalchemy - - 0.54s 38M
3.9 alpine (musl) apscheduler wheel - 0.24s 18.0M
3.9 alpine (musl) apscheduler - - 0.26s 18.0M
3.9 alpine (musl) asyncpg wheel - 0.24s 18.0M
3.9 alpine (musl) asyncpg - - 0.26s 18.0M
3.9 alpine (musl) mongodb sdist - 0.22s 25.9M
3.9 alpine (musl) mongodb - - 0.23s 25.8M
3.9 alpine (musl) redis wheel - 0.24s 21.2M
3.9 alpine (musl) redis - - 0.28s 21.2M
3.9 alpine (musl) sqlalchemy wheel - 0.25s 41.8M
3.9 alpine (musl) sqlalchemy - - 0.26s 41.8M
3.9 slim (glibc) apscheduler wheel 1.9s 0.21s 18M
3.9 slim (glibc) apscheduler - - 0.22s 18M
3.9 slim (glibc) asyncpg wheel 1.8s 0.21s 18M
3.9 slim (glibc) asyncpg - - 0.21s 18M
3.9 slim (glibc) mongodb wheel 3.3s 0.23s 27M
3.9 slim (glibc) mongodb - - 0.22s 27M
3.9 slim (glibc) redis wheel 2.2s 0.22s 22M
3.9 slim (glibc) redis - - 0.22s 22M
3.9 slim (glibc) sqlalchemy wheel 4.0s 0.28s 41M
3.9 slim (glibc) sqlalchemy - - 0.22s 41M
Imports
- BackgroundScheduler
from apscheduler.schedulers.background import BackgroundScheduler - BlockingScheduler
from apscheduler.schedulers.blocking import BlockingScheduler - AsyncIOScheduler
from apscheduler.schedulers.asyncio import AsyncIOScheduler - IntervalTrigger
from apscheduler.triggers.interval import IntervalTrigger - CronTrigger
from apscheduler.triggers.cron import CronTrigger - DateTrigger
from apscheduler.triggers.date import DateTrigger
Quickstart last tested: 2026-04-24
import time
from datetime import datetime
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.interval import IntervalTrigger
def my_job():
print(f"Hello from APScheduler! The time is: {datetime.now()}")
if __name__ == '__main__':
scheduler = BackgroundScheduler()
scheduler.add_job(my_job, IntervalTrigger(seconds=5), id='my_scheduled_job')
print('Starting scheduler. Press Ctrl+C to exit.')
scheduler.start()
try:
# This is here to simulate application activity (for BackgroundScheduler)
while True:
time.sleep(2)
except (KeyboardInterrupt, SystemExit):
scheduler.shutdown()
print("Scheduler shut down successfully.")