We can use a directory structure that is more complex than the flat structure we had earlier. In this case the location of the modules relatively to the scripts is fixed. In this case it is "../lib". We can compute the relative path in each of our scripts. That will ensure we pick up the right module every time we run the script. Regardless of the location of the whole project tree.

print("Importing my_module")
from __future__ import print_function
import os, sys

# import my_module   # ImportError: No module named my_module

print(__file__)   # examples/sys/bin/relative_path.py
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

mypath = os.path.join(project_root, 'lib')
print(mypath) # /Users/gabor/work/training/python/examples/sys/../lib
sys.path.insert(0, mypath)

import my_module   # Importing my_module