Tuesday, March 4, 2014

Error starting django manage.py shell / runserver

So you're hacking away some django code for your next project and decide to test it out on runserver or in django's shell. But then you see this Error: No module named <module> - Not very helpful is it?

Next time this happens, try running runserver/shell (actually any django management command) with the --traceback option to figure out what is really going on.
./manage.py shell --traceback

Traceback (most recent call last):
  File "c:\Python27\lib\site-packages\django\core\management\base.py", line 217, in execute
    translation.activate('en-us')
  File "c:\Python27\lib\site-packages\django\utils\translation\__init__.py", line 105, in activate
    return _trans.activate(language)
  File "c:\Python27\lib\site-packages\django\utils\translation\trans_real.py", line 194, in activate
    _active.value = translation(language)
  File "c:\Python27\lib\site-packages\django\utils\translation\trans_real.py", line 183, in translation
    default_translation = _fetch(settings.LANGUAGE_CODE)
  File "c:\Python27\lib\site-packages\django\utils\translation\trans_real.py", line 160, in _fetch
    app = import_module(appname)
  File "c:\Python27\lib\site-packages\django\utils\importlib.py", line 35, in import_module
    __import__(name)
...
...
...
  File ".\project\models.py", line 2, in <module>
    from csv import DictWriter
ImportError: cannot import name DictWriter
models.py in the project app is importing the csv library which is supposed to be a standard library shipped with python. So now why is it missing features all of a sudden?
>>> import csv
>>> csv
<module 'csv' from 'csv.py'>
>>> import socket
>>> socket
<module 'socket' from 'c:\Python27\lib\socket.pyc'>
Importing csv.py in a separate python shell (not django shell) in the same folder revealed the cause - csv.py was being imported from the root of the project directory and not the usual place (C:\Python27\Lib\ on a windows machine). This one turned out to be just a dummy script that I was working on and for lack of a better name, just decided to call it csv.py. When manage.py scripts are running, it loads models.py's from all installed apps and in my case, one of them inadvertently loaded my custom csv.py, thus overriding the actual python library. This resulted in an ImportError in my case - could even  be something else like an AttributeError for you.

Errors like this can also happen because of cyclic imports (A imports B, B imports C, C imports A). To fix these, look at the traceback, figure out where the cycles are happening, and remove the problematic imports from the __main__ of the file - move these to wherever you are actually using it (like within a function). The interpreter will try running import statements inside functions only upon function invocation and not when the file is being read (unlike import statements in __main__/imports outside function bodies).
from app1.models import ModelA
def view1(request):
    return ModelA.objects.filter(user=request.user)
Instead, rewrite it like this.
def view1(request):
    from app1.models import ModelA
    return ModelA.objects.filter(user=request.user)

You don't have to worry about the performance penalty about re-importing the same module again and again because python loads modules and keeps them in memory inside a dict sys.modules, meaning the next time you try to import the same module, it sees that it's already got a copy with itself and doesn't repeat work.

No comments:

Post a Comment