For most beginning and intermediate programmers, working with multiple directories in Python projects can be frustrating at times. As a Python programmer, it is a best practice to abstract application code into different files and directories and according to their related functionality and data requirements. Moreover, you will have no option but to use existing packages and modules others have written. This will require the ability to work efficiently within multiple directory packages in your project.
Importance of working with multi-level directories in your project code
- Modularity of Code: In order to write solutions for bigger problems, it’s important to divide your projects into smaller portions, where each smaller problem is implemented in a separate subdirectory in your project. This will enable you to concentrate on smaller subproblems, which are less overwhelming and easier to deal with.
- Reusability of Code: It is important for your project code to follow the DRY (Don’t Repeat Yourself) principle. When you find multiple portions of code basically trying to do the same thing, something is not right. When you abstract your code by implementing single or related logic into individual modules and subpackages, you can then use them anywhere in your project by just importing them rather than trying to rewrite them elsewhere in your project.
- Maintainability of Code: This is perhaps the most important reason to do code abstraction. It’s very important that portions of your project code be loosely coupled together. When you have to make modifications to several parts of your project code simply because you made a change to a small portion of your project, then something is definitely wrong. Your project code need not be too interdependent. Interdependence should be kept to the barest minimum. Good project code should enable anyone without knowledge outside the project to easily make changes to it. This will help during team collaboration. When you use subpackages and modules well, you only have to make changes to the specific module you need to change.
However, working with multiple levels of directories in a project can be daunting for programmers starting out and using third-party packages or modules in their own programs. In this article, I provide a simple way to easily handle file importation in multi-level directory project code. (To see how Python projects should be structured, refer to the Python document at the end of this post.)
Importing a file in a multi-level directory structure
In Python syntax, a leading dot indicates the current directory. Each additional dot moves you higher up a directory or package. It is generally advised to use absolute import rather than relative import in your code.
Let’s use a Python project with a directory structure (as shown below) to demonstrate how easy it can be to import from a multi-level directory using both absolute and relative import.
Note: In Python, each directory or subdirectory must be initialized with an __init__.py file for it to be recognized as a package or subpackage. Otherwise, you may get a no-module-found error when trying to import.
When in the myPackage directory, and to access the security.py file in the __init__.py file of the myPackage in the same directory:
import security #absolute import from . import security #relative import
However, for a file one level deeper, when in the __init__.py of myPackage and importing the item.py file in subfolder1:
import subfolder1.item #absolute import from subfolder1 import item #absolute import
For a file two levels deeper, when in the __init__.py of myPackage and importing user.py from subfolder2:
import folder1.folder2.user #absolute import from folder1.folder2 import user #absolute import
The most daunting aspect is having to import a file backward—that is, from a higher level into a file in a lower-level directory. Absolute import makes this easier.
To access security.py from student.py of subfolder2:
import myPackage.security #absolute import from myPackage import security #absolute import from ... import security #relative import
To access accounts.py in subfolder3 from user.py in subfolder2:
import myPackage.subfolder3.accounts #absolute import from myPackage.subfolder3 import accounts #absolute import from ...subfolder3 import accounts #relative import
To access user.py from student.py in the same subfolder2, simply:
import user # python3 from . import user # any python version
Abstracting your code into subpackages or modules will help you write easily maintainable code. I hope this helps reduce headaches when working in a multi-level directory package or module.
Further reading: https://docs.python.org/3/tutorial/modules.html