Django执行manage.py runserver无报错卡住,添加default_app_config后异常
我之前也碰到过一模一样的情况!这种启动卡住却无报错的现象,大概率是循环导入引发的死锁,结合你的代码场景,给你几个实用的解决思路:
问题场景还原
你在component/nodes/__init__.py中添加了配置:
default_app_config = 'component.nodes.apps.NodesConfig'
对应的component/nodes/apps.py代码如下:
from django.apps import AppConfig class NodesConfig(AppConfig): name = 'component.nodes' def ready(self): from component.nodes import signals
执行python manage.py runserver时进程直接卡住,无任何报错,按下Ctrl+C后仅得到部分回溯信息:
^CTraceback (most recent call last): File "manage.py", line 22, in <module> execute_from_command_line(sys.argv) File "/home/storj/storj/...
问题根源分析
Django启动时会按顺序加载各个App的配置,而你在ready()方法中直接导入了signals模块。如果signals.py里又导入了当前App的模型、或者其他依赖于AppConfig初始化完成的模块,就会形成循环依赖链,导致进程卡在启动环节无法推进——而且因为是死锁而非抛出异常,所以没有报错信息。
解决方案
1. 用延迟导入避开启动时的循环依赖
修改apps.py的ready()方法,使用importlib实现延迟导入,避免启动阶段直接触发循环:
from django.apps import AppConfig import importlib class NodesConfig(AppConfig): name = 'component.nodes' def ready(self): importlib.import_module('component.nodes.signals')
2. 检查并消除signals.py中的循环导入
打开component/nodes/signals.py,仔细查看里面的导入语句:
- 如果有类似
from .models import XXX的代码,可以尝试把导入语句移到信号处理函数内部,而不是放在模块顶部; - 如果是其他模块的循环依赖,需要重构代码逻辑,打破循环链。
3. 移除不必要的default_app_config配置
从Django 1.9版本开始,只要你的AppConfig类命名符合[AppName]Config的规范(比如你的NodesConfig对应nodes App),Django会自动发现并加载它,不需要手动在__init__.py中设置default_app_config。如果你的Django版本≥1.9,可以直接删除那行配置,很多时候能直接解决问题。
验证方法
修改完成后,重新执行:
python manage.py runserver
如果进程正常启动,说明问题解决。如果还是卡住,可以用高 verbose 级别查看启动日志,定位具体阻塞点:
python manage.py runserver --verbosity 3
内容的提问来源于stack exchange,提问作者Beliaf

