Opened 4 weeks ago
Closed 4 weeks ago
#36544 closed Bug (duplicate)
In some import sequence ./manage.py raises "populate() isn't reentrant" hiding the original error
Reported by: | living-dev | Owned by: | |
---|---|---|---|
Component: | Core (Management commands) | Version: | 5.2 |
Severity: | Normal | Keywords: | populate reentrant manage.py ImportError |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Hi,
I often add other command line entry points to my project, as a consequence, I ensure that whenever some code use my project code, all the django part is initialized if not already done. This can lead to a import sequence by manage.py that hides the real error.
Here is a reproduction scenario:
$ python -m venv bug $ cd bug/ $ . ./bin/activate $ pip install django==5.2.5 $ django-admin startproject bug $ cd bug $ ./manage.py startapp an_app $ ./manage.py startapp bad_import
Add "an_app" and "bad_import" to INSTALLED_APPS:
INSTALLED_APPS = [ ... 'an_app', 'bad_import', ]
Here the automatic django initialization code:
$ cat > bug/__init__.py << EOF import os import django from django.conf import settings from django.apps import apps if not settings.configured and not apps.loading: os.environ['DJANGO_SETTINGS_MODULE'] = 'bug.settings' django.setup() EOF
And a custom entry point under bug project:
$ cat > bug/cli.py << EOF from django.conf import settings if __name__ == '__main__': print('My CLI entry point:', settings.configured) EOF
At this point both cli and manage.py
are working:
$ python -m bug.cli My CLI entry point: True $ ./manage.py Type 'manage.py help <subcommand>' for help on a specific subcommand. ...
Now we introduce a bad import line because of typo error in the models:
$ echo 'import an_app.model' >> bad_import/models.py
When using our cli entry point, the error is clear:
$ python -m bug.cli Traceback (most recent call last): ... File "/home/debian/Support/django/bug-20250807/bug/bug/bug/__init__.py", line 9, in <module> django.setup() ... File "/home/debian/Support/django/bug-20250807/bug/bug/bad_import/models.py", line 3, in <module> import an_app.model ModuleNotFoundError: No module named 'an_app.model'
But when we use manage.py, the error is hidden:
$ ./manage.py Traceback (most recent call last): ... File "/home/debian/Support/django/bug-20250807/bug/lib/python3.11/site-packages/django/core/management/__init__.py", line 416, in execute django.setup() File "/home/debian/Support/django/bug-20250807/bug/lib/python3.11/site-packages/django/__init__.py", line 24, in setup apps.populate(settings.INSTALLED_APPS) File "/home/debian/Support/django/bug-20250807/bug/lib/python3.11/site-packages/django/apps/registry.py", line 83, in populate raise RuntimeError("populate() isn't reentrant") RuntimeError: populate() isn't reentrant
In fact the error is memorized in django/core/management/__init__.py:381
:
try: settings.INSTALLED_APPS except ImproperlyConfigured as exc: self.settings_exception = exc except ImportError as exc: self.settings_exception = exc
But we finish on this part, that triggers the reentrant populate django/core/management/__init__.py:414
:
# In all other cases, django.setup() is required to succeed. else: django.setup()
I think it could be simply resolved by propagating the memorized exception if django.setup()
fails, so the trace is more explicit:
# In all other cases, django.setup() is required to succeed. else: try: django.setup() except Exception as exc: raise exc from self.settings_exception
In this case the stack trace can help as it shows both the original error and that we also call django.setup()
twice:
$ ./manage.py Traceback (most recent call last): File "/home/debian/Support/django/bug-20250807/bug/lib/python3.11/site-packages/django/core/management/__init__.py", line 382, in execute settings.INSTALLED_APPS ... File "/home/debian/Support/django/bug-20250807/bug/bug/bug/__init__.py", line 9, in <module> django.setup() ... File "/home/debian/Support/django/bug-20250807/bug/bug/bad_import/models.py", line 3, in <module> from an_app.model import Model ModuleNotFoundError: No module named 'an_app.model' The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/home/debian/Support/django/bug-20250807/bug/bug/./manage.py", line 22, in <module> main() ... File "/home/debian/Support/django/bug-20250807/bug/lib/python3.11/site-packages/django/core/management/__init__.py", line 417, in execute django.setup() ... File "/home/debian/Support/django/bug-20250807/bug/lib/python3.11/site-packages/django/apps/registry.py", line 83, in populate raise RuntimeError("populate() isn't reentrant") RuntimeError: populate() isn't reentrant
Best Regards,
Change History (1)
comment:1 by , 4 weeks ago
Keywords: | ImportError added |
---|---|
Resolution: | → duplicate |
Status: | new → closed |
Type: | Uncategorized → Bug |
Thanks for the report. The swallowing of
ImportError
regardless of whether it emanated from a settings module is tracked in #32915. A clear statement of the problem can also be found in #36422.