erewok
erewok

Reputation: 7835

Django Apache ValueError: Attempted Relative Import in non-package

I have seen a number of discussions on ValueError: relative import in non-packge, but the discussions about calling a script do not seem to relate to the problem I am currently having (or if they do, I don't understand well enough how they do...).

Yesterday, I set up a new Ubuntu Server VM running Apache. I have a Python3.4 virtualenv that Apache is using for its interpreter and package directory when it runs my Django application.

I have a directory structure that looks something like the following:

Directory Structure

Django_proj/
    manage.py
    ...

    Django_proj/
      __init__.py
       wsgi.py
       urls.py

       settings/
           __init__.py
           core_settings.py
           prod_settings.py
           local_settings.py
           logging_settings.py

Currently, I am loading local_settings.py, where I have the following relative import:

from .logging_settings import LOGGING

But I get a Traceback in the Apache log that looks like the following:

File "/PATH/TO/VIRTUALENV/lib/python3.4/site-packages/django/utils/importlib.py", line 40, in import_module
      __import__(name)
File "/PATH/TO/Django_proj/Django_proj/local_settings.py", line 12, in <module>
     from .logging_settings import LOGGING
ValueError: Attempted relative import in non-package

Shell Works

This error does not appear if I go to the top-level directory and run (after activating the virtualenv) python manage.py shell: it's able to successfully import local_settings.py and any of my django apps and I can access variables (like LOGGING from django.conf.settings).


wsgi.py

Here's the wsgi.py file, where I went a little nuts adding all of the directories listed to the path:

import os
import sys
sys.path.append('PATH/TO/Django_proj')
sys.path.append('PATH/TO/Django_proj/Django_proj')
sys.path.append('PATH/TO/Django_proj/Django_proj/settings')
os.environ.setdefault("DJANGO_SETTINGS_MODULE",
                      "settings.local_settings")

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

Apache Config

Apache is successfully importing Django and it's using the right Python interpreter (which can be seen in the Traceback), but I thought there might be something weird about how Apache is running the application, so in addition to the paths in wsgi.py, I added everything I could think of to the WSGIDaemonProcess path. Here's my httpd.conf:

LoadModule wsgi_module  modules/mod_wsgi.so

ServerName localhost
WSGIRestrictEmbedded On
WSGILazyInitialization On
WSGIDaemonProcess django-proj.org processes=2 threads=12 python-path=/virtualenv/PATH/lib/python3.4/site-packages:/virtualenv/PATH/bin:/PATH/TO/Django_proj:/PATH/TO/Django_proj/Django_proj:/PATH/TO/Django_proj/Django_proj/settings
WSGIProcessGroup django-proj.org

But I don't understand well enough about the conditions that are happening when Apache spins up Python in order to run wsgi.py. I figured if I just added all the relevant paths everywhere, then the problem should go away and Python should be able to find and import logging_settings.py locally from local_settings.py. However, it appears that local_settings.py is a non-package.

Anyway, I am confused why I am receiving this error and I would appreciate the input of informed Stack Overflowers.

Edit: I should mention that I have read the following document a number of times as well, and it is useful: https://code.google.com/p/modwsgi/wiki/IntegrationWithDjango

Upvotes: 1

Views: 989

Answers (1)

erewok
erewok

Reputation: 7835

Well, this is embarrassing, but I don't really know what I did to fix this. However, it is fixed. Here's what I did.

I was having an unrelated problem with my installed-from-source Python shell not using readline (no up for history), which I fixed as described here: https://stackoverflow.com/a/25942732/1748754

I needed to recompile Python after building readline, and because this was all on a VM (set up with Vagrant and Ansible), I just destroyed it and rebuilt it.

After that, I noticed that in my wsgi.py, I was importing settings in a weird way, so I just appended that main project path and imported settings in the following way:

wsgi.py

import os
import sys
sys.path.append('/PATH/TO/Django_proj/Django_proj/')
os.environ.setdefault("DJANGO_SETTINGS_MODULE",
                      "Django_proj.settings.local_settings")

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

I made this change because I realized that wgsi.py and manage.py were importing settings.py in different ways, so I changed wsgi.py to be like manage.py.

It's hard to believe that readline being missing was causing me other errors and, if so, this is probably highly specific and not useful to anyone else.

Problematically, it only occurred to me to check whether it worked after I had done all of this other work.

Anyway, it's a bit embarassing not to know what solved the problem and it involved a full os-teardown-and-rebuild (which is pretty easy with Vagrant/Ansible) but there it is.

Upvotes: 1

Related Questions