You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django多进程启动触发AppRegistryNotReady错误解决方案咨询

解决Django多进程中AppRegistryNotReady错误的方案

核心原因

你的问题出在Windows环境下multiprocessing默认使用spawn启动模式:子进程会重新导入整个模块,而非继承父进程的内存状态。主进程中已经初始化的Django环境不会被传递到子进程,导致子进程在导入模型时触发AppRegistryNotReady错误。

解决方案

无需引入Celery,只要在子进程中手动初始化Django环境,并延迟导入Django相关模块即可。以下是针对你代码的具体修改步骤:

1. 给Worker进程添加Django初始化逻辑

在每个Worker进程的run方法开头,先完成Django的初始化,再导入需要用到的模块。以VcenterWorker为例,修改Processes\Vcenter.py:

# Python imports:
from multiprocessing import Process
import os
import django

def init_django():
    # 设置Django配置模块路径,替换为你项目的settings模块
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "VMwareInventory.settings")
    django.setup()

class VcenterWorker(Process):
    def __init__(self, queue, vcenter_list):
        Process.__init__(self)
        self.queue = queue
        self.list = vcenter_list
        self.name = "vCenter_worker_process"
        self.start()

    def run(self):
        # 先初始化Django环境
        init_django()
        # 延迟导入涉及Django模型的模块,避免提前触发模型加载
        from VMwareInventory.VMwareRest.VMwareRest import RESTVCenter
        from VMwareInventory.models import Vcenter

        while True:
            # 建议传递模型ID而非实例,避免序列化问题
            vcenter_id = self.queue.get()
            try:
                vcenter = Vcenter.objects.get(id=vcenter_id)
                self.list.remove(vcenter)
                self.vcscrape(vcenter.name, vcenter.user, vcenter.password)
            finally:
                self.queue.task_done()

    @staticmethod
    def vcscrape(name, user, pwd):
        vc_scrape = RESTVCenter(name, user, pwd)
        vc_scrape.join()
        return

2. 同步修改其他Worker类

对StorageWorker和BackupWorker做完全相同的修改:在run方法开头调用init_django(),并延迟导入相关模块。

3. 优化队列传递的内容

避免直接将Django模型实例放入队列,改为传递模型的id。在threading\scraping.py的run方法中,添加任务到队列时做如下修改:

# 原代码(假设你有类似逻辑):
# for vc in vcenters:
#     self.vcenter_queue.put(vc)

# 修改为传递ID:
for vc in vcenters:
    if vc not in self.vcenter_list:
        self.vcenter_list.append(vc)
        self.vcenter_queue.put(vc.id)

原理说明

  • django.setup()会完成Django的核心初始化流程:加载应用配置、初始化数据库连接、注册模型等,让子进程具备使用ORM的能力。
  • 延迟导入Django相关模块,避免在模块顶级(子进程启动时)就加载模型,此时Django还未初始化,必然触发错误。
  • 传递模型ID而非实例,避免了Django模型实例序列化可能带来的问题,同时减少队列传输的数据量。

额外注意事项

  • 确保DJANGO_SETTINGS_MODULE的路径正确,与你项目的settings文件一致。
  • 如果你的RESTVCenter类内部直接导入了Django模型,也要确保这些导入是在Django初始化之后执行的(比如移到类的方法内部,而非模块顶级)。

内容的提问来源于stack exchange,提问作者Jimmy Fort

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 11:25:30