Opened 4 years ago

Closed 4 years ago

#18850 closed Bug (duplicate)

After doing some recursive import, the gobal value of `X` that defined with value `1` is automatically set to `None`, if class derived from `models.Model`

Reported by: Omid Raha Owned by: nobody
Component: Database layer (models, ORM) Version: 1.4
Severity: Normal Keywords:
Cc: Florian Apolloner 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 attached a sample project(test_dj),
this project can run with django 1.4 or later,
the problem I found is that after doing some recursive import,
the gobal value of X that defined with value 1 is automatically set to None, if class derived from models.Model

You can test this issue:

  1. Extract test_dj project
  2. run python manage.py shell
  3. doing test:

In [1]: from test_dj.package_A.models import X_IS_OK,X_IS_None

In [2]: X_IS_OK()
Ok, X is 1

In [3]: X_IS_None()
Wow ! why X is None ?

Attachments (1)

test_dj.tar (24.0 KB) - added by Omid Raha 4 years ago.
Sample test project

Download all attachments as: .zip

Change History (6)

Changed 4 years ago by Omid Raha

Attachment: test_dj.tar added

Sample test project

comment:1 Changed 4 years ago by Omid Raha

To simplify the problem, i print X in constructor of model(without call supper of it),
but if you change the 'init' to another method, This problem still occurs ,for example:

class X_IS_None(models.Model):

def test(self):

print 'Wow ! why X is {0} ?'.format(X)

comment:2 Changed 4 years ago by Florian Apolloner

Cc: Florian Apolloner added

Stack from the importError in get_models from django.db.models.loading:

Traceback (most recent call last):
File "test.py", line 2, in <module>
get_models()
File "/home/florian/sources/django.git/django/db/models/loading.py", line 192, in get_models
self._populate()
File "/home/florian/sources/django.git/django/db/models/loading.py", line 72, in _populate
self.load_app(app_name, True)
File "/home/florian/sources/django.git/django/db/models/loading.py", line 98, in load_app
models = import_module('.models', app_name)
File "/home/florian/sources/django.git/django/utils/importlib.py", line 35, in import_module
__import__(name)
File "/home/florian/dev/test_dj/test_dj/package_B/models.py", line 2, in <module>
from test_dj.package_B.package_BA.module_BA import Unit_BA
File "/home/florian/dev/test_dj/test_dj/package_B/package_BA/module_BA.py", line 1, in <module>
from test_dj.module_D import Unit_D
File "/home/florian/dev/test_dj/test_dj/module_D.py", line 5, in <module>
from test_dj.package_A.models import Unit_A
File "/home/florian/dev/test_dj/test_dj/package_A/models.py", line 21, in <module>
from test_dj.package_C.package_CA.module_CA import Unit_CA
File "/home/florian/dev/test_dj/test_dj/package_C/package_CA/module_CA.py", line 1, in <module>
from test_dj.package_C.models import Unit_C
File "/home/florian/dev/test_dj/test_dj/package_C/models.py", line 2, in <module>
from test_dj.package_B.models import Unit_B
ImportError: cannot import name Unit_B

So this is Code doesn't work in Python at all, and Django silences the import errors :/ Restructuring INSTALLED_APPS might help in that specific case.

comment:3 Changed 4 years ago by Omid Raha

Yes, i know that with reordering the app in INSTALLED_APPS, the problem can be solved, but why django silences the import errors? can say django, don't do that, and raise import errors?
and in this specific case why X is None and at least isn't undefined.

Version 1, edited 4 years ago by Omid Raha (previous) (next) (diff)

comment:4 Changed 4 years ago by Łukasz Rekucki

Sadly in Python, at the time of writing, you can't easily tell if the ImportError was raised because the module you tried did not exist, failed to execute or tried to import something else that raised an ImportError. What Django could do is to check if the module exists and reraise when appropriate (like https://github.com/django/django/blob/soc2010/app-loading/django/core/apps.py does).

As for X is None, that's a puzzle. I'm not yet sure if it's legitimate behavior or a bug in Python's import mechanics, but if you check the module by hand, the X has value 1, so that other X must come from some different deinitialized version of the module.

comment:5 Changed 4 years ago by Aymeric Augustin

Resolution: duplicate
Status: newclosed

As explained by lrekucki, short of restructuring the app import machinery, there isn't much we can do in Django to provide a better error message in this case. This restructuring is actually a work in progress, it's the app-loading branch, see #3591.

Note: See TracTickets for help on using tickets.
Back to Top