Django中APScheduler启动报错AppRegistryNotReady问题求助
Django中APScheduler启动触发AppRegistryNotReady错误
我在Django项目的settings.py中添加了以下APScheduler代码,期望应用启动时自动运行定时任务:
import atexit from apscheduler.schedulers.background import BackgroundScheduler from main.utils import run_employee_import scheduler = BackgroundScheduler() scheduler.add_job(run_employee_import, "interval", minutes=2) scheduler.start() # Shut down the scheduler when exiting the app atexit.register(lambda: scheduler.shutdown())
但启动应用时触发了如下错误:
raise AppRegistryNotReady("Apps aren't loaded yet.") django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.
注:我已将run_employee_import替换为简单的pass,错误仍然存在。
问题原因
settings.py在Django启动流程中加载时机过早,此时Django的应用注册表还未完成初始化,直接在这里启动调度器就会触发上述错误。必须等到Django所有应用加载完成后,再启动APScheduler。
解决方案
方案1:利用AppConfig的ready方法(推荐)
这是Django官方推荐的应用初始化完成后执行代码的方式,适合开发和生产环境:
- 打开主应用(比如
main)下的apps.py,修改AppConfig类:
from django.apps import AppConfig import atexit import os from apscheduler.schedulers.background import BackgroundScheduler from .utils import run_employee_import class MainConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = 'main' def ready(self): # 开发模式下Django会重复加载应用,加此判断避免调度器重复启动 if os.environ.get('RUN_MAIN') == 'true': scheduler = BackgroundScheduler() scheduler.add_job(run_employee_import, "interval", minutes=2) scheduler.start() atexit.register(lambda: scheduler.shutdown())
- 确保
settings.py的INSTALLED_APPS中,你的应用是用AppConfig路径注册的:
INSTALLED_APPS = [ # 其他应用... 'main.apps.MainConfig', ]
方案2:使用自定义管理命令
如果需要独立控制调度器的启停,可以用这种方式:
- 在
main应用下创建management/commands目录(没有就新建),然后创建start_scheduler.py文件:
from django.core.management.base import BaseCommand import atexit from apscheduler.schedulers.background import BackgroundScheduler from main.utils import run_employee_import class Command(BaseCommand): help = '启动APScheduler后台调度器' def handle(self, *args, **options): scheduler = BackgroundScheduler() scheduler.add_job(run_employee_import, "interval", minutes=2) scheduler.start() self.stdout.write(self.style.SUCCESS('调度器启动成功')) # 保持进程运行,按Ctrl+C停止 try: while True: pass except KeyboardInterrupt: scheduler.shutdown() self.stdout.write(self.style.SUCCESS('调度器已关闭'))
- 启动时先运行Django服务,再新开终端执行调度器命令:
python manage.py runserver # 新终端窗口执行 python manage.py start_scheduler
内容的提问来源于stack exchange,提问作者Kaiss B.
相关产品推荐
相关产品推荐

