Python – ImportError: No module named django.core.wsgi

apachecentosdjangomod-wsgipython

I'm moving a web application from a Windows environment to CentOS 5.11 and Apache, and with everything installed, I'm receiving a 500 when I try to load up the site. The error log shows this:

mod_wsgi (pid=5461): Target WSGI script '/usr/local/treehouse/wsgi/index.wsgi' cannot be loaded as Python module.
mod_wsgi (pid=5461): Exception occurred processing WSGI script '/usr/local/treehouse/wsgi/index.wsgi'.
Traceback (most recent call last):
  File "/usr/local/treehouse/wsgi/index.wsgi", line 11, in <module>
    from django.core.wsgi import get_wsgi_application
ImportError: No module named 'django.core.wsgi'

I found this question (and the related ones), which appears to be similar but none of the answers there fix the issue. I'm not running in a virtualenv, and django appears to be installed correctly, as I can run the offending statement:

>>> from django.core.wsgi import get_wsgi_application

in the interactive Python interpreter and it works just fine. Here's the script causing the error (it's just the default index.wsgi that you see everywhere you look for this stuff):

import os, sys
sys.path.append('/usr/local/treehouse/apple')
sys.path.append('/usr/local/treehouse/apple/apple')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "apple.settings")

from django.core.wsgi import get_wsgi_application application = get_wsgi_application()

Obviously the last line causes the error, but here's the fun part: the last line remains the problem, even if I add this just above it:

import django.core
import django.core.handlers

Both of the underlying packages import without a hitch (django.core.wsgi is just a thin wrapper around some functionality in django.core.handlers.wsgi). It's only when I try to access the wsgi packages that problems occur. Inspecting sys.path within this script shows all the right directories (/usr/local/lib/python3.4/site-packages, etc.). And again, running the exact same code from the interactive interpreter causes no errors.

I tried an uninstall/reinstall of django (pip install django==1.6.5), then I reset the VM to a totally clean snapshot and rebuilt/reinstalled everything, and still I get the exact same behavior.

What is going on?

Best Solution

Some of the django source files pulled down by pip are saved with Windows line endings: that is, they end with \r\n rather than \n. On *nix systems, this has the effect of breaking imports in affected files, because instead of looking for django.core.wsgi, it tries to import django.core.wsgi\r.

This is why django.core.handlers can still be imported: the __init__.py file is empty, so there are no line endings to corrupt.

To fix it, run dos2unix on affected files. I'm not sure how many files are actually affected (except that it's many of them) so I just hit all of them with a quick Python script from the interpreter:

import os
from os.path import abspath, join

for root, _, files in os.walk('/usr/local/lib/python3.4/site-packages/django'):
    for f in files:
        os.system('dos2unix %s' % abspath(join(root, f)))

Et voilĂ , no more import errors!


Storytime

I stumbled on this issue after I began hacking on the django source files in desperation. I edited django/core/__init__.py (normally empty) by adding this:

from . import wsgi

I modified index.wsgi to include this:

import django.core
django.core.wsgi  # no-op to see if we can access it

and ended up with a fascinating new error:

Traceback (most recent call last):
  File "/usr/local/treehouse/wsgi/index.wsgi", line 11, in <module>
    import django.core
  File "/usr/local/lib/python3.4/site-packages/django/core/__init__.py", line 1, in <module>
    from . import wsgi
  File "/usr/local/lib/python3.4/site-packages/django/core/wsgi.py", line 1, in <module>
    from django.core.handlers.wsgi import WSGIHandler
ImportError: No module named 'django.core.handlers.wsgi'

So from within django/core/__init__.py, I can access django/core/wsgi.py. But django.core.handlers.wsgi is out of reach. I deleted the changes to reproduce the original error--but the error had changed. Now I was getting the No module named 'django.core.handlers.wsgi' even without the explicit relative import.

This was when it hit me. I opened up django/core/handlers/wsgi.py in gedit, clicked the end of a line, pressed the spacebar, deleted the insertion, and saved the file. It should have been a no-op. But when I restarted the server, suddenly the import error had moved on to a different django import. The only logical explanation was that the line endings were wrong, and by re-saving the file in gedit, I was silently fixing them.

Related Question