Code

#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: OmidRaha Owned by: nobody
Component: Database layer (models, ORM) Version: 1.4
Severity: Normal Keywords:
Cc: apollo13 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 OmidRaha 20 months ago.
Sample test project

Download all attachments as: .zip

Change History (6)

Changed 20 months ago by OmidRaha

Sample test project

comment:1 Changed 20 months ago by OmidRaha

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

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 20 months ago by apollo13

  • Cc apollo13 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 20 months ago by OmidRaha

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, doesn't do that, and raise import errors?
and in this specific case why X is None and at least isn't undefined.

Last edited 20 months ago by OmidRaha (previous) (diff)

comment:4 Changed 18 months ago by lrekucki

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 17 months ago by aaugustin

  • Resolution set to duplicate
  • Status changed from new to closed

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.

Add Comment

Modify Ticket

Change Properties
<Author field>
Action
as closed
as The resolution will be set. Next status will be 'closed'
The resolution will be deleted. Next status will be 'new'
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.