#36544: In some import sequence ./manage.py raises "populate() isn't reentrant" hiding the original error -------------------------------------+------------------------------------- Reporter: living-dev | Type: | Uncategorized Status: new | Component: Core | (Management commands) Version: 5.2 | Severity: Normal Keywords: populate reentrant | Triage Stage: manage.py | Unreviewed Has patch: 0 | Needs documentation: 0 Needs tests: 0 | Patch needs improvement: 0 Easy pickings: 0 | UI/UX: 0 -------------------------------------+------------------------------------- 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, -- Ticket URL: <https://code.djangoproject.com/ticket/36544> Django <https://code.djangoproject.com/> The Web framework for perfectionists with deadlines. -- You received this message because you are subscribed to the Google Groups "Django updates" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-updates+unsubscr...@googlegroups.com. To view this discussion visit https://groups.google.com/d/msgid/django-updates/01070198856e56f9-c3c19699-5d1d-4d6b-841d-392b065f48cf-000000%40eu-central-1.amazonses.com.