Python Relative Imports: Guide & Error Fixes

1. Overview of import statements and relative path imports in Python

When writing programs in Python, you use import statements to efficiently reuse modules. In this import statement, relative path imports are especially useful when there are flexible dependencies between modules. This article explains how to use relative paths in Python’s import statements and their advantages.

What is a relative path import?

A relative path import is a way to import other modules based on the location of the current module. It is especially useful for large projects or package development with multiple modules. Using relative path imports clarifies dependencies between modules, making project maintenance easier. For example, suppose you have a directory structure like the following.
project/
    ├── main.py
    ├── package/
    │   ├── module_a.py
    │   └── sub_package/
    │       └── module_b.py
To import module_a.py from module_b.py using a relative path, you would write:
from ..module_a import some_function
In this way, using relative paths lets you flexibly import modules based on the directory hierarchy.

2. Difference Between Relative and Absolute Paths

There are two types of import statements in Python: relative paths and absolute paths. The difference between them lies in how the target module is specified.

Absolute Path Import

An absolute path import specifies a module starting from the project’s root directory.
For example, in a project with the following structure, if you want to import module_a.py into main.py using an absolute path, you would write it as follows:
from package.module_a import some_function

This method is useful when the overall structure of the project is clear and the location of modules remains consistent.

Relative Path Import

On the other hand, relative path imports import modules based on the location of the current module. Relative path imports can be relatively flexible, especially when the structure of the project changes. This makes it possible to improve code reusability while maintaining dependencies between modules.

For example, the following code shows how to import a module that is located one directory above the current module:

from ..module_a import some_function
Which option to choose depends on the size and complexity of the project. In general, absolute path imports are suitable when the location of modules is fixed, while relative path imports are more appropriate when changes occur frequently.
RUNTEQ(ランテック)|超実戦型エンジニア育成スクール

3. Importing Using Relative Paths

Importing Modules from the Same Directory

When importing a module that resides in the same directory, you don’t need any complex specifications—just use the module name directly. For example, if module_a.py and module_b.py are in the same directory, you can import them as follows.
import module_a
To import a specific function or class, you would do it like this:
from module_a import some_function

Importing from a Parent Directory

When importing a module located in a parent directory, use .. to move up a level before specifying the module. For example, to import from one level up, you would write:
from ..module_a import some_function

Importing from a Subdirectory

When importing a module from a subdirectory, specify the directory name and module name separated by a dot. For example, you can import a module from a subdirectory as follows.
from sub_package.module_b import some_function
Using relative paths provides the major advantage that your code remains flexible even if the project’s directory structure changes.

4. Importing Modules Within a Package

Python has the concept of a “package” for organizing modules. Packages are handy for grouping multiple modules together, especially in large projects. You can also import modules within a package using relative paths.

Package Structure and __init__.py File

When creating a package, you need to add a __init__.py file to its directory. This file tells Python to recognize the directory as a package. Below, we’ll explain using a project with the following structure.
project/
    ├── main.py
    ├── package/
    │   ├── __init__.py
    │   ├── module_a.py
    │   └── sub_package/
    │       ├── __init__.py
    │       └── module_b.py

Relative Path Import of Modules Within a Package

For example, to import module_a.py from module_b.py using a relative path, you would write:
from ..module_a import some_function
This .. means moving up one level from the current directory. In this way, you can share functions and classes between modules within the package. Also, when importing a module from the same package using a relative path, you can specify it easily with a dot.
from .module_a import some_function
This allows modules in the project to interact concisely, and you won’t need major code changes even if the directory structure changes.

5. Common Errors and Their Solutions

Python relative path imports can produce several typical errors. This section explains these errors and how to resolve them.

ImportError: attempted relative import with no known parent package

This error is a common one that occurs when trying to import a module using a relative path, especially when the script is run directly. For example, code like the following can cause the problem.
from ..module_a import some_function
This error occurs because Python cannot recognize the script’s parent package. In Python, a module must be clearly recognized as part of a package. When a script is run directly, using a relative path is likely to cause an error.

Solution

One way to avoid this issue is to use sys.path to explicitly set the module search path. For example, you can add the parent directory to the search path using sys.path.append() as follows.
import sys
sys.path.append('..')
from module_a import some_function
This allows Python to locate the module correctly.

ModuleNotFoundError

Another common error is ModuleNotFoundError. This occurs when the specified module cannot be found. When trying to import a module via a relative path, it may be because the module’s location is incorrect or sys.path is not set correctly.

Solution

To resolve this issue, review the import statements and verify that the module actually exists. Also, by using sys.path.append() to explicitly specify directories where Python can find the module, you can avoid the error.

6. Practical Examples and Applications

Here we present concrete code examples using relative path imports. This shows how you can leverage relative paths in real projects.

Example: Importing from a Parent Directory

Assume a project structure like the following.
project/
    ├── main.py
    ├── package/
    │   ├── module_a.py
    │   └── sub_package/
    │       └── module_b.py
The code that imports the function some_function from module_b.py module_a.py is shown below.
# module_b.py
from ..module_a import some_function

def use_function():
    some_function()
In this code, .. is used to go up one directory, and the function is imported from module_a. This approach is handy when sharing functions or classes across modules that span multiple directories.

Example: Importing Modules Using sys.path

Next, we show an example of importing a parent‑directory module using sys.path.append().
# module_b.py
import sys
sys.path.append('..')
from module_a import some_function

def use_function():
    some_function()
In this method, sys.path adds the parent directory, allowing Python to locate module_a correctly. This approach is especially effective when running scripts directly.

7. Conclusion

In this article, we provided an in‑depth look at relative‑path imports in Python’s import statements. Relative‑path imports are especially useful for large projects and package development because they let you manage dependencies between modules flexibly. However, they can be prone to errors, so proper configuration and the use of sys.path are important. Understanding the benefits of relative‑path imports and applying them in real projects enables more efficient code management.