Install & Compatibility
Where this runs
tested against v1.13.1 · pip install
no network on importno background threads
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslpy 3.10–3.920 runs
installs and imports cleanly · install 0.0s · import 0.765s · 25.5MB
glibcpy 3.10–3.920 runs
installs and imports cleanly · install 3.6s · import 0.696s · 26MB
24MB installed
● package 24MB
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
APScheduler
✓ from flask_apscheduler import APScheduler
This quickstart demonstrates how to initialize Flask-APScheduler with a Flask application and define a recurring task using a decorator. It includes a basic configuration and ensures the scheduler starts with the application. Note the `use_reloader=False` for development to avoid multiple scheduler instances, which is a common issue.
from flask import Flask
from flask_apscheduler import APScheduler
import os
app = Flask(__name__)
class Config:
SCHEDULER_API_ENABLED = True
# Example job store - use an appropriate one for production
# SCHEDULER_JOBSTORES = {
# 'default': {'type': 'sqlalchemy', 'url': 'sqlite:///jobs.sqlite'}
# }
# Example job execution (APScheduler default is 'threadpool')
# SCHEDULER_EXECUTORS = {
# 'default': {'type': 'threadpool', 'max_workers': 20}
# }
app.config.from_object(Config())
scheduler = APScheduler()
scheduler.init_app(app)
scheduler.start()
# Define a simple job using the decorator
@scheduler.task('interval', id='my_interval_job', seconds=5, misfire_grace_time=900)
def job_function():
print(f"Hello from scheduled job! Time: {scheduler.app.config.get('SCHEDULER_API_ENABLED')}")
@app.route('/')
def index():
return "Flask-APScheduler is running! Check console for job output."
if __name__ == '__main__':
# In development, you might need to handle the reloader carefully.
# For simple cases, `use_reloader=False` or specific deployment setup is needed.
# For production, use a WSGI server (e.g., Gunicorn) and ensure only one worker starts the scheduler.
app.run(debug=True, use_reloader=False)
Debug
Known issues
breakingFlask-APScheduler version 1.13.0 and older versions might not be compatible with Flask 3.x. Version 1.13.1 added explicit support for Flask 3.x.fixUpgrade to Flask-APScheduler 1.13.1 or newer for Flask 3.x compatibility. Ensure Flask >= 2.2.5 is installed.
affects: <1.13.1
breakingVersion 1.13.0 dropped support for Python versions older than 3.8 and removed several deprecated methods. Attempting to run on older Python versions or using removed methods will result in errors.fixEnsure your Python environment is 3.8 or newer. Review your code for deprecated methods if upgrading from a significantly older version.
affects: <1.13.0
gotchaFlask-APScheduler explicitly pins APScheduler to version 3.x (e.g., in 1.12.0) to prevent unexpected errors due to significant changes in APScheduler 4.x. Directly installing APScheduler 4.x might cause incompatibilities.fixDo not manually install APScheduler 4.x if using Flask-APScheduler. Let Flask-APScheduler manage the APScheduler dependency or consult documentation for explicit compatibility.
affects: All versions that pin APScheduler to 3.x
gotchaWhen deploying with a WSGI server (like Gunicorn), ensure only one worker process starts the APScheduler instance. APScheduler 3.x is designed to run with a single worker process, and multiple instances can lead to jobs running multiple times or other inconsistencies.fixConfigure your WSGI server to run with a single worker process, or implement logic to ensure `scheduler.start()` is called only once (e.g., in the main process before forking workers, or within a specific worker).
affects: All versions using APScheduler 3.x
gotchaIf using a persistent jobstore (e.g., SQLAlchemyJobStore), do not register jobs from configuration files (e.g., `app.config`). These jobs should be registered using decorators (`@scheduler.task`) or via the `scheduler.add_job()` method to avoid duplication on application restart.fixRegister persistent jobs only through decorators or `add_job` calls, not via `SCHEDULER_JOBS` in your Flask configuration.
affects: All versions
gotchaIf your scheduled jobs need to interact with the Flask application context (e.g., accessing `current_app`, `Flask-SQLAlchemy`'s `db` object), you must explicitly wrap the context-dependent operations within `with scheduler.app.app_context():`.fixWrap Flask context-dependent code inside jobs with `with scheduler.app.app_context():`. Remember to commit database sessions if performing DB operations.
affects: All versions
Errors
Common errors & fixes
ModuleNotFoundError: No module named 'flask_apscheduler'
The `flask_apscheduler` package is not installed in the Python environment being used by your Flask application, or there's a virtual environment mismatch.
fixEnsure the package is installed in the correct environment: `pip install Flask-APScheduler`
AttributeError: 'APScheduler' object has no attribute 'task'
This error typically occurs when trying to use the `@scheduler.task` decorator for defining jobs with an older version of `flask-apscheduler` or when the scheduler object has not been properly initialized or started.
fixEnsure you are using a recent version of `flask-apscheduler` (1.11.0 or newer for the `@task` decorator) and that the scheduler has been initialized with `scheduler.init_app(app)` and started with `scheduler.start()`. If issues persist, consider using `scheduler.add_job()` instead of the decorator.
RuntimeError: Working outside of application context
Scheduled jobs execute in a separate thread/process outside of Flask's request context, meaning Flask-specific objects like `current_app`, `g`, or database connections managed by Flask extensions are not available by default.
fixWrap your job's logic that requires the Flask application context within `with scheduler.app.app_context():` to manually push the application context.
Scheduler not starting/jobs not running (e.g., with Gunicorn or FLASK_DEBUG=True and reloader)
Flask-APScheduler, by default, avoids starting the scheduler when Flask's reloader is active (`FLASK_DEBUG=True`) or in certain multi-process WSGI server configurations (like Gunicorn without `--enable-threads`), to prevent duplicate job execution.
fixFor development, ensure `FLASK_DEBUG` is not set or handle it explicitly. For production with WSGI servers like Gunicorn, ensure threads are enabled (`gunicorn --worker-class gthread --threads 4 ...` or `--enable-threads` for uWSGI). Alternatively, configure an environment variable or flag to explicitly control scheduler startup in multi-process environments.
TypeError: can't pickle _thread._local objects
This error occurs when using persistent job stores (e.g., SQLAlchemyJobStore) and a job function or its arguments contain unpicklable objects, such as `_thread.local` objects or non-module-level functions/lambdas, which cannot be serialized for storage.
fixEnsure scheduled functions are module-level (not nested or lambdas) and that any arguments passed to jobs are picklable. Refactor code to avoid passing Flask-specific context objects directly as job arguments when using persistent job stores. Instead, access necessary resources by pushing an application context within the job as described in the 'Working outside of application context' fix.
Upgrade
Version history
1.13.1latest on PyPI · released Nov 7, 2023
Audit
Dependencies
PythonrequiredRequires Python 3.8 or higher.
FlaskrequiredRequires Flask 2.2.5 or higher.
APSchedulerrequiredExplicitly pinned to version 3.x due to potential breaking changes in APScheduler 4.x.