Django importing another file from another package - python

I have the following folder structure
app/
app/helpers/
app/helpers/methodhelper.py
app/methods/
app/methods/method.py
and I'm trying to import a function from methodhelper.py inside method.py
so I tried the following:
import app.helpers.methodhelper
OR
from app.helpers.methodhelper import function1
OR
import helpers.methodhelper
and I get:
"No module named app.helpers.methodhelper"
Important to note: helpers/__init__.py already exists
How should this be done ?

Your Django project's default path is in the root directory of the project (where the manage.py file is). You can either add the sub directories below that to your PYTHONPATH (easily done by appending to sys.path) or you can import that function using the full module path:
from projectname.app.helpers.methodhelper import function1
When I start a Django project, I always add
PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
to my settings.py. This path looks similar to /home/kyle/django_project_name/. Inside that directly is manage.py.
From there, also in my settings.py, I include:
sys.path.append(os.path.join(PROJECT_ROOT, 'django_project_name'))
This makes my apps importable without the need to include my project name in the module path.

you need to add the module in settings.py file

Related

Python help working with packages and modules

I need some help with working with a folder structure in python. I was given an structure like this:
/main-folder
/assets
somefiles.txt
/integrations
/module-folder
__init__.py
ingestion.py
__init__.py
models.py
Inside ingestion.py I have:
import os
from models import MyModel
PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
some_function()
some_processing()
if __name__ == "__main__":
some_function()
Both __init__.py mentioned above are empty.
So I need to process some info and use the models module to store them. when trying to execute intestion.py directly from its dir it says: No module named 'models'. So I'm guessing I have to execute the whole thing as a package. I have no idea how should I import a module located above the package and can't touch the structure.
Any help woud be appreciated.
What you have to do is to add the module's directory to the PYTHONPATH environment variable. If you don't want to do this however, You can modify the sys.path list in your program where the Python interpreter searches for the modules to import, the python documentation says:
When a module named spam is imported, the interpreter first searches for a built-in module with that name. If not found, it then searches for a file named spam.py in a list of directories given by the variable sys.path. sys.path is initialized from these locations:
the directory containing the input script (or the current directory).
PYTHONPATH (a list of directory names, with the same syntax as the shell variable PATH).
the installation-dependent default.
After initialization, Python programs can modify sys.path. The directory containing the script being run is placed at the beginning of the search path, ahead of the standard library path. This means that scripts in that directory will be loaded instead of modules of the same name in the library directory. This is an error unless the replacement is intended.
Knowing this, you can do the following in your program:
import sys
# Add the main-folder folder path to the sys.path list
sys.path.append('/path/to/main-folder/')
# Now you can import your module
from main-folder import models
# Or just
import main-folder

Importing from parent directory gets error

The project structure on my local machine is setup like this:
python/
__init__.py
readText.py
testing/
__init__.py
removeDuplicates.py
In removeDuplicates.py I am trying to import as follows:
from python import readText
This gives: ImportError: No module name 'python'
My init.py in both folders are blank by the way.
You need the parent directory of your python subdirectory to be present in sys.path. If you execute your script from that directory, the import should work. But the easiest way to do this is to export the environment variable PYTHONPATH.
You want to import something from the parent directory, use
from .. import readText
see relative imports:
https://docs.python.org/2.5/whatsnew/pep-328.html

Import file from parent directory?

I have the following directory structure:
application
tests
main.py
main.py
application/main.py contains some functions.
tests/main.py will contain my tests for these functions but I can't import the top level main.py. I get the following error:
ImportError: Import by filename is not supported.
I am attempting to import using the following syntax:
import main
What am I doing wrong?
If you'd like your script to be more portable, consider finding the parent directory automatically:
import os, sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# import ../db.py
import db
You must add the application dir to your path:
import sys
sys.path.append("/path/to/dir")
from app import object
Or from shell:
setenv PATH $PATH:"path/to/dir"
In case you use windows:
Adding variable to path in windows.
Or from the command line:
set PATH=%PATH%;C:\path\to\dir
Please mind the diff between PYTHONPATH, PATH, sys.path.
Late to the party - most other answers here are not correct unfortunately - apart LennartRegebro's (and BrenBarn's) which is incomplete. For the benefit of future readers - the OP should, first of all, add the __init__.py files as in
root
application
__init__.py
main.py
tests
__init__.py
main.py
then:
$ cd root
$ python -m application.tests.main
or
$ cd application
$ python -m tests.main
Running a script directly from inside its package is an antipattern - the correct way is running with the -m switch from the parent directory of the root package - this way all packages are detected and relative/absolute imports work as expected.
First of all you need to make your directories into packages, by adding __init__.py files:
application
tests
__init__.py
main.py
__init__.py
main.py
Then you should make sure that the directory above application is on sys.path. There are many ways to do that, like making the application infto a package and installing it, or just executing things in the right folder etc.
Then your imports will work.
You cannot import things from parent/sibling directories as such. You can only import things from directories on the system path, or the current directory, or subdirectories within a package. Since you have no __init__.py files, your files do not form a package, and you can only import them by placing them on the system path.
To import a file in a different subdirectory of the parent directory, try something like this:
sys.path.append(os.path.abspath('../other_sub_dir'))
import filename_without_py_extension
Edit: Missing closing bracket.
in python . exists for same directory, .. for parent directory
to import a file from parent directory you can use ..
from .. import filename (without .py extension)

Make library folder visible to all python scripts in different dir/subdir with a GAE project directory

I have the following directory structure for my GAE project:
project:
library:
lib1.py
lib2/x.py
lib2/y.py
apps:
app1/app1.py
app2/app2.py
app2/async.py
how do I make the library folder visible to any app that will ever be created in the apps dir and its subdirs?
Alternatively it's possible to add the library directory to the sys.path
Create a __init__.py inside the library folder.
import os
import sys
def add_lib_path():
lib_directory = os.path.dirname(os.path.abspath(__file__))
if lib_directory not in sys.path:
sys.path.insert(0, lib_directory)
In every file where you import libraries from the library folder add this code before the import statements:
from lib import add_lib_path
add_lib_path()
In this case all your imported libraries will behave as expected.
PYTHONPATH specifies a series of folders to start searches for imported modules.
GAE adds the folder that contains app.yaml to your PYTHONPATH.
So assuming that app.yaml is in the root of that structure (ie the folder that contains "library" and "apps") then any of your apps can import relative to there...
from library import lib1
from library/lib2 import x

How to import a Django project settings.py Python file from a sub-directory?

I created a sub-directory of my Django project called bin where I want to put all command-line run Python scripts. Some of these scripts need to import my Django project settings.py file that is in a parent directory of bin.
How can I import the settings.py file from a sub-directory of the project?
The code that I use in my command-line script to set into the "Django context" of the project is:
from django.core.management import setup_environ
import settings
setup_environ(settings)
This works fine if the script is in the root directory of my project.
I tried the following two hacks to import the settings.py file and then setup the project:
import os
os.chdir("..")
import sys
sys.path = [str(sys.path[0]) + "/../"] + sys.path
The cruel hack can import settings.py, but then I get the error:
project_module = __import__(project_name, {}, {}, [''])
ValueError: Empty module name
I think your approach may be over-complicating something that Django 1.x provides for you. As long as your project is in your python path, you can set the environment variable DJANGO_SETTINGS_MODULE at the top of your script like so:
import os
os.environ['DJANGO_SETTINGS_MODULE'] = 'myproject.settings'
In your command line script where you need to read your settings, simply import the settings module from 'django.conf' as you would do in your application code:
from django.conf import settings
And presto, you have your settings and a Django-enabled environment for your script.
I personally prefer to set my DJANGO_SETTINGS_MODULE using '/usr/bin/env' in a bash script called 'proj_env' so I don't have to repeat it
#!/bin/bash
proj_env="DJANGO_SETTINGS_MODULE=myproject.settings"
/usr/bin/env $proj_env ${*}
With this, now I can run any python script with my Django application in context:
proj_env python -m 'myproject.bin.myscript'
If you use virtualenv, this also gives you a good place to source the activate script.
etc. etc.
This is going one level up from your question, but probably the best solution here is to implement your scripts as custom manage.py (django-admin.py) commands. This gives you all of Django's functionality (including settings) for free with no ugly path-hacking, as well as command-line niceties like options parsing. I've never seen a good reason to write Django-related command-line scripts any other way.
Add the parent directory to your path:
import sys
sys.path.append('../')
import settings
Update from comments:
Don't forget the __init__.py file in
the directory that has your
settings.py – S.Lott
Let's say your project directory is /opt/someProject/`
This has files like:
manage.py
Now you have you may have your sub directory anywhere, does not matter.
Eg. subdirectory could be like:
/opt/someproject/dir1/dir2
Now for you to import your project settings inside /opt/someProject/dir1/dir2
You need to set your PYTHONPATH variable
export PYTHONPATH=/opt/someproject/
Now to import modules from bin
from someproject import bin

Categories