Opened 8 years ago

Closed 7 years ago

#2947 closed defect (duplicate)

ImportError raised in my management.py is swallowed

Reported by: paul@… Owned by: nobody
Component: Core (Other) Version:
Severity: normal Keywords:
Cc: Triage Stage: Design decision needed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: UI/UX:

Description

This code in "management.py" has the same bug as was reported in ticket 2669

http://code.djangoproject.com/ticket/2669

# Import the 'management' module within each installed app, to register
# dispatcher events.
for app_name in settings.INSTALLED_APPS:

try:

import(app_name + '.management', , , [])

except ImportError:

pass

If mysite/myapp/management.py tries to import a non-existent module, or imports a module that imports a non-existent module, then management.py is ignored silently. This is very hard to diagnost and debug! At first, I had no idea why management.py seemed to cease to exist. Then after a while, I guessed, based on my knowledge of how Python works.

The solution should be the same as for 2669. Perhaps it would be good to audit all situations where ImportError is raised.

Attachments (2)

management_import_patch.diff (2.0 KB) - added by paul@… 8 years ago.
Patch to fix management.py import bug
manage_bug.zip (5.7 KB) - added by paul@… 8 years ago.
Test case for management.py fix.

Download all attachments as: .zip

Change History (6)

comment:1 Changed 8 years ago by anonymous

Maybe there should be a helper function that is used globally instead of import.

import sys
import imp

def module_exists(modulename):
    try:
        imp.find_module(modulename)
        return True
    except ImportError:
        return False


def import_if_exists(modulename):
    try:
        module = __import__(modulename)
        return module
    except ImportError, e:
        if module_exists(modulename):
            raise
        else:
            return None

def test():
    # this test depends upon the existance of a "foo.py" which imports
    # some other non-existent module (or otherwise raises an ImportError)
    assert import_if_exists("xml.dom"), "xml.dom does exist"
    assert not load_if_exists("foobar"), "foobar does not exist"
    try:
        raises_import_error = load_if_exists("foo")
        assert False, "Should not have gotten here"
    except ImportError:
        pass
    print "Tests succeeded!"

test()

Changed 8 years ago by paul@…

Patch to fix management.py import bug

Changed 8 years ago by paul@…

Test case for management.py fix.

comment:2 Changed 8 years ago by paul@…

Note that the patch is still not quite correct. It works only if the parent of the project directory is in sys.path but I think that Django is designed to not depend upon this, right?

comment:3 Changed 8 years ago by Simon G. <dev@…>

  • Triage Stage changed from Unreviewed to Design decision needed

comment:4 Changed 7 years ago by jacob

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

This is really a symptom of a bigger problem with Python exceptions themselves (search python-dev for discussion of chained exceptions to see the long history here). I'm wary of working around it since it seems like a lot of code; a better aproach would be to re-raise the exception using the --traceback mechanism added in #4431.

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