If you ever wondered how current path for module can be retrieved reliably in Python, there is a relatively simple way to do this. Each module has a __file__ variable that can be used for it.
The answer is pretty simple.
import os
path = os.path.abspath(__file__)
dir_path = os.path.dirname(path)
And that’s all. If you put this in your module, dir_path variable represents current directory of the module. That’s pretty cool thing, because it doesn’t matter what is the directory the program was called from, dir_path will always represent proper path for each module. And one of the benefits for using this simple construct is an ability to modify sys.path.
What for you might ask. Well, let’s assume that you have your own project that spans multiple subdirectories. However, you have also supporting scripts or programs which are used only from command-line and de facto they are not part of your primary application. They can be used for example for database migration, sanitizing, fixing, cleanup, backups and all other administrative purposes you can imagine, which are not part of your application. If your main project has it’s own virtual environment like e.g. using Django or Pylons, it’s hard to use module import namespace from within the subdirectory, such as the subdirectory was your import root. You always have to add primary project namespace and that somehow defies the purpose of supporting scripts, which are used for the primary application, but are not part of it in the strict sense.
If you have your project virtual environment set up and primary application resides under for example /myawesomeproject/ and your supporting scripts reside under /myawesomeproject/scripts, and some model modules for supporting scripts reside under /myawesomeproject/scripts/lib then if you’re importing modules from this lib subdirectory you’d have to do:
from myawesomeproject.scripts.lib import somemodule
But when you want this script to be used as a standalone, without reliance on the virtual environment of the primary application, you would certainly want to use:
from lib import somemodule
And here’s where the dir_path variable comes to exactly serve this purpose. When executing your supporting script, you can do:
PYTHONPATH=$PYTHONPATH:. python myscript.py
But then, it can be a problem for your users, because they have to remember they should force Python system path change. However with dir_path you can put this code into the beginning of your main script’s module to automatically set correct system path, so the imports would work without any problems:
import sys, os
path = os.path.abspath(__file__)
dir_path = os.path.dirname(path)
sys.path.append(dir_path)
And that’s all. After putting this code at the very beginning of your main module for the script, you can proceed with other imports (they will treat main module path as import root) and your script’s program code.
PS. Just remember to put empty __init__.py files to each subdirectory you would use as a collection for your imports for this to work correctly.