First of all let me clarify you that importing an entire module, if you are going to use a part of it, then is not a good idea. Instead of that you can use from
to import specific function under a library/package. By doing this, you make your program efficient in terms of memory and performance.
To know more refer these:
- 'import module' or 'from module import'
- difference between import and from
Net let us look into the solution.
Before starting off with the solution, let me clarify you the use of __init__.py
file. It just tells the python interpreter that the *.py files present there are importable which means they are modules and are/maybe a part of a package.
So, If you have N no of sub directories you have to put __init__.py
file in all those sub directories such that they can also be imported. Inside __init__.py
file you can also add some additional information like which path should be included, default functions,variables,scope,..etc. To know about these just google about __init__.py
file or take some python library and go through the same __init__.py
file to know about it. (Here lies the solution)
More Info:
- modules
- Be pythonic
So as stated by @Sushant Chaudhary your project structure should be like
proj-dir
--|--__init__.py
--package1
--|--__init__.py
--|--module1.py
--package2
--|--__init__.py
--|--module2.py
So now, If I put __init__.py
file under my directory like above, Will
it be importable and work fine?
yes and no.
Yes :
If you are importing the modules within that project/package directory.
for example in your case
you are importing package1.module1 in pakage2.module2 as from package1 import module1
.
Here you have to import the base dir inside the sub modules, Why? the project will run fine if you are running the module from the same place. i.e: inside package2 as python module2.py, But will throw ModuleNotFoundError
If you run the module from some other directory. i.e: any other path except under package2 for example under proj-dir as python package2/module2.py
. This is what happening in your case. You are running the module from project-dir.
So How to fix this?
1- You have to append basedir path to system path in module2.py as
from sys import path
dir_path = "/absolute/path/to/proj-dir"
sys.path.insert(0, dir_path)
So that module2 will be able to find package1 (and module1 inside it).
2- You have to add all the sub module paths in __init__.py
file under proj-dir.
For example:
#__init__.py under lxml
# this is a package
def get_include():
"""
Returns a list of header include paths (for lxml itself, libxml2
and libxslt) needed to compile C code against lxml if it was built
with statically linked libraries.
"""
import os
lxml_path = __path__[0]
include_path = os.path.join(lxml_path, 'includes')
includes = [include_path, lxml_path]
for name in os.listdir(include_path):
path = os.path.join(include_path, name)
if os.path.isdir(path):
includes.append(path)
return includes
This is the __init__.py
file of lxml (a python library for parsing html,xml data). You can refer any __init__.py
file under any python libraries having sub modules.ex (os,sys). Here I've mentioned lxml because I thought it will be easy for you to understand. You can even check __init__.py
file under other libraries/packages. Each will have it's own way of defining the path for submodules.
No
If you are trying to import modules outside the directory. Then you have to export the module path such that other modules can find them into environment variables. This can be done directly by appending absolute path of the base dir to PYTHONPATH or to PATH.
To know more:
- PATH variables in OS
- PYTHONPATH variable
So to solve your problem, include the paths to all the sub modules in __init__.py
file under proj-dir and add the /absolute/path/to/proj-dir either to PYTHONPATH
or PATH
.
Hope the answer explains you about usage of __init__.py
and solves your problem.