Tuesday, September 19, 2017

Python/Django Standalone Script - Import by filename is not supported

Leave a Comment

I have the following script and it's meant to be a standalone Django script so I can run python my_script.py from the command line. It used to work with Django 1.8, after I upgrade to Django 1.11, I'm getting the following error:

Traceback (most recent call last):   File "app.py", line 8, in <module>     django.setup()   File "C:\python27\lib\site-packages\django-1.11.5-py2.7.egg\django\__init__.py", line 22, in setup     configure_logging(settings.LOGGING_CONFIG, settings.LOGGING)   File "C:\python27\lib\site-packages\django-1.11.5-py2.7.egg\django\conf\__init__.py", line 56, in __getattr__     self._setup(name)   File "C:\python27\lib\site-packages\django-1.11.5-py2.7.egg\django\conf\__init__.py", line 41, in _setup     self._wrapped = Settings(settings_module)   File "C:\python27\lib\site-packages\django-1.11.5-py2.7.egg\django\conf\__init__.py", line 110, in __init__     mod = importlib.import_module(self.SETTINGS_MODULE)   File "C:\python27\lib\importlib\__init__.py", line 37, in import_module     __import__(name) ImportError: Import by filename is not supported. 

This is my python script

# standalone django setup import os, sys, logging, django prj_dir = os.path.abspath(os.path.dirname(os.path.dirname(__file__))) logging.basicConfig(level=logging.INFO) logging.info("PRJ_DIR: %s" % prj_dir) sys.path.append(prj_dir) os.environ.setdefault("DJANGO_SETTINGS_MODULE", "%s.settings" % prj_dir.split("/")[-1]) django.setup()  ... ... 

6 Answers

Answers 1

It seems you're trying to split a file path by the forward slash / while running your script on Windows where path separator is the backslash \. Use os.path.basename instead of manually dealing with the stings (.split("/")[-1]):

>>> import os >>> os.path.basename(r'/home/user/project') 'project' >>> os.path.basename(r'c:\users\user\project') 'project' 

In comparison:

>>> r'/home/user/project'.split("/")[-1] 'project'  # works >>> r'c:\users\user\project'.split("/")[-1] 'c:\\users\\user\\project'  # error 

Answers 2

Don't reinvent the wheel. There is a cool manage command on django extensions that lets you run scripts on the django context.

https://django-extensions.readthedocs.io/en/latest/runscript.html

Answers 3

Others have pointed out an issue with your path manipulation, however the cause of your actual import exception is that you are setting DJANGO_SETTINGS_MODULE to the name of a file.

It needs to be the name of a Python module. In other words, your settings file should end in .py and you should pass the name of it (without .py), or the importable path to it - exactly as you would type it in an import statement.

If your settings are in my_settings.py, then you would set the variable to my_settings.

Here is a simplified example of a one-page django application taken from the excellent Lightweight Django book's excerpt:

import sys   from django.conf import settings   settings.configure(     DEBUG=True,     SECRET_KEY='thisisthesecretkey',     ROOT_URLCONF=__name__,     MIDDLEWARE_CLASSES=(         'django.middleware.common.CommonMiddleware',         'django.middleware.csrf.CsrfViewMiddleware',         'django.middleware.clickjacking.XFrameOptionsMiddleware',     ), )   from django.conf.urls import url from django.http import HttpResponse   def index(request):     return HttpResponse('Hello World')   urlpatterns = (     url(r'^$', index), )   if __name__ == "__main__":     from django.core.management import execute_from_command_line      execute_from_command_line(sys.argv) 

Answers 4

The error is in

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "%s.settings" % prj_dir.split("/")[-1]) 

If you run this script from the same folder as manage.py, it will return the name of the manage.py folder instead settings.py folder resulting managepy_folder.settings

when it should output settingspy_folder.settings to access the app

Test with :

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settingspy_folder.settings") 

if it that was the problem, if you want use the same algorithm or something similar in multiple projects, you need a pattern to modify the current folder name to indicate the settings.py folders name, using the same folders name in both wouldn't require modification.

if that doesn't fix please post your settings.py file

Answers 5

If your script is in the same folder as settings.py, the code should be like this:

import os, sys, logging, django prj_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) logging.basicConfig(level=logging.INFO) logging.info("PRJ_DIR: %s" % prj_dir) sys.path.append(prj_dir) os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{}.settings".format(os.path.basename(prj_dir))) django.setup() 

else, if your script is in the parent folder of settings.py:

import os, sys, logging, django prj_dir = os.path.dirname(os.path.abspath(__file__)) logging.basicConfig(level=logging.INFO) logging.info("PRJ_DIR: %s" % prj_dir) sys.path.append(prj_dir) os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{}.settings".format(os.path.basename(prj_dir))) django.setup() 

Answers 6

in the line: os.environ.setdefault( "DJANGO_SETTINGS_MODULE", "myproject.settings") # should be like in import command )

Just use python module path: like "myproject.settings" instead of path like /opt/myproject/settings" or "c:\myproject\settings.py"

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment