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

Django多进程运行时循环导入与Apps未加载问题求助

Django多进程调用数据库:解决Apps aren't loaded yet与循环导入问题

问题场景

在Django项目中使用多进程执行数据库查询时,触发Apps aren't loaded yet.错误;尝试在数据库查询模块添加import django; django.setup()后,又出现循环导入错误。仅在多进程调用时出现问题,单进程模式下功能正常。

项目代码示例

models.py

from django.db import models

class Document(models.Model):
    name = models.CharField(max_length=20)
    text = models.CharField(max_length=200)

db_request.py

from .models import Document

def get_all_documents():
    return Document.objects.all()

services.py

from multiprocessing import Process
from .db_request import get_all_documents

def stream():
    docs = get_all_documents()

def start_streams_documents():
    pr = Process(target=stream)
    pr.start()
    pr.join()

admin.py

from .models import Document
from .services import start_streams_documents

@admin.register(Document)
class MachineAdmin(admin.ModelAdmin):
    list_display = ('name','text')

    change_list_template = 'admin/document_table_changelist.html'

    def get_urls(self):
        urls = super().get_urls()
        my_urls = [path('start_streams/', self.start_streams)]
        return my_urls + urls

    def start_streams(self, request):
        start_streams_documents()
        return HttpResponseRedirect("../")

报错堆栈信息

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\Users\fr3st\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\spawn.py", line 120, in spawn_main
    exitcode = _main(fd, parent_sentinel)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\fr3st\AppData\Local\Programs\Python\Python311\Lib\multiprocessing\spawn.py", line 130, in _main
    self = reduction.pickle.load(from_parent)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\fr3st\Desktop\Screener V3\app\documents\services.py", line 3, in <module>
    from .db_request import get_all_documents
  File "C:\Users\fr3st\Desktop\Screener V3\app\documents\db_request.py", line 2, in <module>
    django.setup()
  File "C:\Users\fr3st\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\__init__.py", line 24, in setup
    apps.populate(settings.INSTALLED_APPS)
  File "C:\Users\fr3st\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\apps\registry.py", line 125, in populate
    app_config.ready()
  File "C:\Users\fr3st\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\contrib\admin\apps.py", line 27, in ready
    self.module.autodiscover()
  File "C:\Users\fr3st\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\contrib\admin\__init__.py", line 50, in autodiscover
    autodiscover_modules("admin", register_to=site)
  File "C:\Users\fr3st\AppData\Local\Programs\Python\Python311\Lib\site-packages\django\utils\module_loading.py", line 58, in autodiscover_modules
    import_module("%s.%s" % (app_config.name, module_to_search))
  File "C:\Users\fr3st\AppData\Local\Programs\Python\Python311\Lib\importlib\__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\fr3st\Desktop\Screener V3\app\documents\admin.py", line 6, in <module>
    from .services import start_streams_documents
ImportError: cannot import name 'start_streams_documents' from partially initialized module 'documents.services' (most likely due to a circular import) (C:\Users\fr3st\Desktop\Screener V3\app\documents\services.py)

问题分析

  1. 多进程应用未加载错误:Django启动时会加载所有应用配置,但子进程启动时不会继承这一状态,直接调用ORM会触发Apps aren't loaded yet.。
  2. 循环导入问题:在模块级别调用django.setup()会触发Django自动扫描admin模块,而admin模块又导入了services模块,形成services → db_request → django.setup() → admin → services的循环依赖链。

修复方案

方案1:子进程内部延迟初始化Django与导入依赖

修改services.py,将Django初始化和数据库查询的导入逻辑移到子进程执行的函数内部:

from multiprocessing import Process

def stream():
    # 子进程内部单独初始化Django
    import django
    django.setup()
    # 延迟导入避免模块加载阶段的循环依赖
    from .db_request import get_all_documents
    docs = get_all_documents()

def start_streams_documents():
    pr = Process(target=stream)
    pr.start()
    pr.join()
  • 子进程独立初始化Django,不依赖父进程的应用状态
  • 延迟导入避免了模块加载阶段的循环引用

方案2:admin模块延迟导入services

修改admin.py,将services的导入从模块级别移到方法内部:

from .models import Document
from django.http import HttpResponseRedirect
from django.urls import path

@admin.register(Document)
class MachineAdmin(admin.ModelAdmin):
    list_display = ('name','text')
    change_list_template = 'admin/document_table_changelist.html'

    def get_urls(self):
        urls = super().get_urls()
        my_urls = [path('start_streams/', self.start_streams)]
        return my_urls + urls

    def start_streams(self, request):
        # 方法内部延迟导入,打破循环依赖
        from .services import start_streams_documents
        start_streams_documents()
        return HttpResponseRedirect("../")

配合方案1的services.py修改,即可彻底解决两个问题。

关键注意事项

  • 禁止在模块级别(文件顶部)调用django.setup(),这会干扰Django的正常启动流程
  • 多进程中涉及Django ORM的操作,必须在子进程内部单独初始化Django
  • 延迟导入是解决Django循环依赖的常用手段,尤其适用于admin与业务服务模块之间的交互

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 22:35:09