{"id":233,"library":"APScheduler","title":"APScheduler","description":"Advanced Python Scheduler — schedule Python functions to run at specified times or intervals. Current stable version is 3.11.2. A completely rewritten 4.x is in pre-release with a different API (apscheduler.Scheduler instead of BackgroundScheduler, etc.) — 4.x is NOT installed by pip install APScheduler. Two concurrent stable lines: use 3.x for production. The 3.x vs 4.x API confusion is the #1 footgun.","status":"active","version":"3.11.2","language":"python","source_language":"en","source_url":"https://apscheduler.readthedocs.io/en/3.x/","tags":["scheduling","cron","interval","background-jobs","periodic-tasks"],"install":[{"cmd":"pip install APScheduler","lang":"bash","label":"Installs 3.x stable (NOT 4.x)"},{"cmd":"pip install APScheduler[sqlalchemy]","lang":"bash","label":"With SQLAlchemy persistent job store"},{"cmd":"pip install APScheduler[redis]","lang":"bash","label":"With Redis job store"}],"dependencies":[{"reason":"Required for timezone support. Installed automatically.","package":"tzlocal>=2.0","optional":false},{"reason":"Required for timezone handling. Installed automatically.","package":"pytz","optional":false},{"reason":"Required for SQLAlchemyJobStore. Install via APScheduler[sqlalchemy].","package":"sqlalchemy>=1.4","optional":true},{"reason":"Required for RedisJobStore. Install via APScheduler[redis].","package":"redis","optional":true}],"imports":[{"wrong":"from apscheduler.schedulers.background import BackgroundScheduler","symbol":"BackgroundScheduler","correct":"from apscheduler.schedulers.background import BackgroundScheduler"},{"wrong":"from apscheduler.triggers.cron import CronTrigger","symbol":"CronTrigger","correct":"from apscheduler.triggers.cron import CronTrigger"},{"wrong":"from apscheduler.triggers.interval import IntervalTrigger","symbol":"IntervalTrigger","correct":"from apscheduler.triggers.interval import IntervalTrigger"}],"quickstart":{"code":"from apscheduler.schedulers.background import BackgroundScheduler\nfrom datetime import datetime\nimport time\n\ndef job_function():\n    print(f'Job ran at {datetime.now()}')\n\n# BackgroundScheduler runs in a daemon thread\nscheduler = BackgroundScheduler()\n\n# Interval trigger\nscheduler.add_job(job_function, 'interval', seconds=10, id='my_job')\n\n# Cron trigger (every day at 9:30am)\nscheduler.add_job(job_function, 'cron', hour=9, minute=30)\n\n# Date trigger (one-off)\nfrom datetime import timedelta\nscheduler.add_job(\n    job_function,\n    'date',\n    run_date=datetime.now() + timedelta(minutes=1)\n)\n\n# Must start explicitly\nscheduler.start()\nprint('Scheduler started. Press Ctrl+C to exit.')\n\ntry:\n    while True:\n        time.sleep(1)\nexcept KeyboardInterrupt:\n    scheduler.shutdown()","lang":"python","description":"3.x stable API. BackgroundScheduler runs in a thread. Always call start() and shutdown()."},"warnings":[{"fix":"For production: pip install APScheduler installs stable 3.x. For 4.x pre-release: pip install 'APScheduler>=4.0a1'. The 3.x and 4.x APIs are completely incompatible.","message":"APScheduler 4.x (a complete rewrite) is in pre-release and has a completely different API. pip install APScheduler installs 3.x — NOT 4.x. 4.x docs and tutorials showing from apscheduler import Scheduler will raise ImportError on 3.x installs.","severity":"breaking","affected_versions":"4.x pre-release vs 3.x stable"},{"fix":"Always call scheduler.start() after adding jobs. For Flask/Django: call it in app startup, not module level.","message":"scheduler.start() must be called explicitly. Creating a scheduler and adding jobs without calling start() does nothing — jobs never run.","severity":"gotcha","affected_versions":"3.x"},{"fix":"Configure a persistent job store: scheduler = BackgroundScheduler(jobstores={'default': SQLAlchemyJobStore(url='sqlite:///jobs.sqlite')})","message":"Jobs are lost on restart unless a persistent job store (SQLAlchemy, Redis, MongoDB) is configured. The default MemoryJobStore holds jobs only in RAM.","severity":"gotcha","affected_versions":"3.x"},{"fix":"Run the scheduler in a single dedicated process. Use a persistent job store with coalesce=True and max_instances=1. Or use a task queue (Celery, RQ) for multi-process environments.","message":"Running multiple processes each with their own scheduler (e.g. gunicorn with multiple workers) causes duplicate job execution. APScheduler 3.x has no inter-process coordination.","severity":"gotcha","affected_versions":"3.x"},{"fix":"Web apps: use BackgroundScheduler. Standalone scheduler scripts: use BlockingScheduler. Async apps: use AsyncIOScheduler.","message":"BlockingScheduler blocks the main thread — use it only when the scheduler IS the application. BackgroundScheduler runs in a daemon thread and is suitable for running alongside a web app.","severity":"gotcha","affected_versions":"3.x"},{"fix":"Always set timezone: BackgroundScheduler(timezone='UTC') or use pytz: BackgroundScheduler(timezone=pytz.timezone('America/New_York'))","message":"All times are naive (timezone-unaware) unless you configure a timezone. Scheduled jobs may run at wrong times during DST transitions.","severity":"gotcha","affected_versions":"3.x"}],"env_vars":null,"search_vec":"'1':67 '3':53,58 '3.11.2':19 '4':23,39,61 'advanc':2 'api':33,63 'apschedul':1,47 'apscheduler.scheduler':34 'background':73 'background-job':72 'backgroundschedul':37 'complet':21 'concurr':49 'confus':64 'cron':70 'current':15 'differ':32 'etc':38 'footgun':68 'function':7 'instal':43,46 'instead':35 'interv':14,71 'job':74 'line':51 'period':76 'periodic-task':75 'pip':45 'pre':28 'pre-releas':27 'product':56 'python':3,6 'releas':29 'rewritten':22 'run':9 'schedul':4,5,69 'specifi':11 'stabl':16,50 'task':77 'time':12 'two':48 'use':52 'version':17 'vs':60 'x':24,40,54,59,62","created_at":"2026-03-27T05:03:37.021088+00:00","updated_at":"2026-04-15T18:59:10.409778+00:00","problems":null,"ecosystem":"pypi","meta_description":null,"install_score":100,"quickstart_score":0,"quickstart_tag":"stale","pypi_latest":"3.11.3","cli_name":"","cli_version":null,"type":"library","homepage":null,"github":"https://github.com/agronholm/apscheduler","docs":"https://apscheduler.readthedocs.io/en/3.x/","changelog":"https://apscheduler.readthedocs.io/en/3.x/versionhistory.html","pypi":"https://pypi.org/project/APScheduler/","npm":null,"openapi_spec":null,"status_page":null,"smithery":null,"categories":["workflow","database"],"base_url":null,"auth_type":null,"provenance":{"verified_status":"passing","verified_at":"2026-06-30","last_verified":"2026-08-27","next_check":"2026-07-30","install_tag":"verified"}}