I was debugging an issue with our Django app at work today; an admin.py file wasn't being picked up, and nothing was appearing in the admin pages. It turned that an ImportError was being thrown in the admin.py and Django was interpreting this as the file not existing.

I'm assuming that the reason for this is that Django uses __import__ to import the module, and catches ImportError's if the admin.py doesn't exist. The trouble with this is that if admin.py does exist, and throws an ImportError of its own, Django will also interpret that as a missing admin.py – which can be misleading.

The only solution I can think of to more accurately handle this would be to programmaticaly examine the traceback to determine where the ImportError is thrown. If the traceback is one level deep, we know that the ImportError was thrown because the module doesn't exists. If it is greater than one level then we know the module was found, but has thrown an ImportError of its own.

Here's a simple proof of concept:

import traceback
import sys

def check_import(name):
    except ImportError:
        exceptionType, exceptionValue, exceptionTraceback = sys.exc_info()
        return len(traceback.extract_tb(exceptionTraceback)) > 1
    return True

print check_import("os")
print check_import("noimport")
print check_import("anotherlevel")
import thismoduledoesnotexist

This produces the following when run:


It would be nice if Django did something similar for its implicit imports. I think the best behaviour would be re-raise the ImportError if it the module does actually exist. That way, it is clear what the problem is. I may attempt to write a patch at some point, unless someone knows of a better solution.

This blog post was posted to It's All Geek to Me on Monday March 30th, 2009 at 7:35PM

5 Responses to "Misleading ImportErrors in Django"

  • March 30th, 2009, 9:27 p.m.

    What version/revision of Django are you using?. Since r10088 __import__ isn't used anymore in Django trunk (Brett Cannon's importlib is now used and included in Django utils library) together with the imp module.

    See http://code.djangoproject.com/browser/django/trunk/django/contrib/admin/__init__.py#L40 [code.djangoproject.com]

  • March 30th, 2009, 10 p.m.

    An earlier version that that it seems. Problem solved! :-)

  • March 31st, 2009, 5:39 p.m.

    Wouldn't you want to have Django throw something subclassed from ImportException, so you could tell the difference?

  • April 1st, 2009, 7:46 a.m.

    yes, django sometimes throws really wired error

  • December 11th, 2009, 7:38 a.m.

    Wouldn't you want to have Django throw something subclassed from ImportException

Leave a Comment

You can use bbcode in the comment: e.g. [b]This is bold[/b], [url]http://www.willmcgugan.com[/url], [code python]import this[/code]
Preview Posting...
Previewing comment, please wait a moment...
Will McGugan

My name is Will McGugan. I am an unabashed geek, an author, a hacker and a Python expert – amongst other things!

You are reading my tech blog. See the homepage for my other blogs.

Search for Posts
Possibly related posts
Popular Tags
Recent Comments
def thousands_with_commas(number): new_number = [] number = str(number) mod_value = len(number) % 3 counter = 3 if len(number) 4: return ...
don't know why this was tempting.. (#1)import re from collections import Counter, OrderedDict cnt=Counter() with open(./t) as f: #--- strip ...
- Mike on Python Coder Test
Hello! I've seen this test and tried to do them. Result added bellow. First path: def thousands_with_commas(i): i = str(i) ...
Why another framework? what wrong with django, pyramid, flask?will be have answer for this question in the docs)
Hi! Really great code, good work! But trying to use it on a responsive site, it didn't resize images. So, ...
© 2008 Will McGugan.

A technoblog blog, design by Will McGugan