SoFunction
Updated on 2025-04-11

A brief analysis of absolute and relative imports in Python

If you are working on a Python project with multiple files, you may have had to use the import statement before. Import can be confusing even for heavy Python users (like me) who have multiple projects! You may be reading this article because you want to have a deeper understanding of imports in Python, especially absolute and relative imports.

1 Quick Introduction to Imports

Python modules are files with .py extensions, and Python packages are any folders that have modules (or in Python 2 is a folder containing __init__.py files). When a code in one module needs to access the code in another module or package, you need to import it.

But how to have a module, suppose you import the os module like this:

import os

The first thing Python does is look up the module named os system in . This is the cache of all modules that were imported before. The sys module provides a series of variables and functions about the Python running environment. If the name is not found in the module cache, Python will continue to search for a list of built-in modules. These modules are pre-installed with Python and can be found in the Python standard library. If the name is still not found in the built-in module, Python searches it in the defined directory list. This list usually includes the current directory, first searching for that directory.

To summarize, Python has three main steps to find a module:

1 by looking from the loaded module

2 Looking for the Python standard library, the Python annotation library is the modules installed through pip install

3. Look through the included directory list. The current directory will usually be automatically imported. Of course, you can also add the path you specify.

When Python finds the module, it binds it to a name in the local scope. This means that os is now defined and os can be used in the current file without throwing a ModuleNotFoundError. If the module is not found, a ModuleNotFoundError is thrown, as shown below:

import os

But another issue to note is that there will be security issues when importing modules. Please note that there are some significant security risks for Python import systems. This is mainly due to its flexibility. For example, the module cache is writable and can be overwritten with the import system. Importing from third-party packages can also put your application at security threats.

2 syntax of import statement

Now that you know how import statements work, let's explore their syntax. You can import packages and modules. (Note that importing a package is actually importing the package's __init__.py file as a module.) You can also import specific objects from a package or module.

There are usually two types of import syntax. When using modules directly, you can directly import modules, as shown below:

2.1 Basic use

import os

os can be a package or a module. When you use the second syntax, you will import from another package or module. Here is an example

from os import path

The path can be a module, a subpacket, or an object, such as a class or a function. You can also choose to rename the imported resource as follows:

import os as so

This will rename the imported os to so. Now it must be referenced as so or it will not be recognized.

2.2 Import declaration style

PEP 8 is the official style guide for Python, and there are some tips when writing import statements. See PEP 8 for details/#imports

The summary is as follows:

  • Imports should always be written at the top of the file, after any module comments and document strings.
  • Import should be divided into the following three categories according to its purpose:
    • Standard library import (Python built-in module)
    • Related third-party imports (modules installed but not belonging to the current application)
    • Local application import (module belonging to the current application)
  • Each import must be separated by spaces

It is also a good idea to sort the import alphabetical order in each import group. This makes it easier to find specific imports, especially when there are many imports in a file. Here is an example of how to style the import statement. The following import statement is divided into three different groups, separated by spaces. In each group, they are also arranged alphabetically.

'''
     The formatted import is as follows
 '''
# Standard Libraryimport datetime
import os

# Third-party libraryfrom flask import Flask

# Local library# import local_module

3 Absolute import and relative import

3.1 Absolute import

You've mastered how to write import statements and how to style them like a professional. Now it's time to learn a little about absolute import. Absolute import specifies that the resource to be imported uses its full path from the project root folder.

Suppose you have the following directory structure:

└── project
    ├── package1
    │   ├──
    │   └──
    └── package2
        ├── __init__.py
        ├──
        ├──
        └── subpackage1
            └──

The current directory project contains two subdirectories package1 and package2. The package1 directory has two files, and.

The package2 directory contains three files: two modules and, and an initialization file __init__.py. It also contains a directory, and subpackage contains a file.

Let's assume the following:

  • package1/ contains a function function1.
  • package2/__init__.py contains a class1.
  • package2/subpackage1/ contains a function function2.

Here is a practical example of absolute import:

from package1 import module1
from package1.module2 import function1
from package2 import class1
from package2.subpackage1.module5 import function2

The content in module2 is as follows:

def function1():
    passs

The content in __init__.py in package2 is as follows:

class class1():
    def __init__():
        return

The content in package2.subpackage1.module5 is as follows:

def function2():
    pass

Note that each package or file must be provided with a detailed path from the top-level package folder. This is a bit similar to its file path, but we use dots (.) instead of slashes (/).

Imports are preferred because they are very clear and direct. Just by looking at the statement, you can easily know exactly where the imported resources are. Additionally, the absolute import is still valid even if the current location of the import statement changes. In fact, PEP 8 explicitly recommends absolute import.

However, sometimes absolute imports can become very verbose, depending on the complexity of the directory structure. Imagine a statement like this:

from package1.subpackage2.subpackage3.subpackage4.module5 import function6

Too ridiculous, right? Fortunately, relative import is a good choice in this case!

3.2 Relative import

Relative import specifies the resources to be imported relative to the current location (i.e. where the import statement is located). There are two types of relative imports: implicit and explicit. Implicit relative imports are deprecated in Python3, so I will not cover them here.

The syntax of relative import depends on the current location and the location of the module, package, or object to be imported. Here are some examples of relative imports:

from .some_module import some_class
from ..some_package import some_function
from . import some_class

You can see that there is at least one point in each of the import statements above. Relative import uses point notation to specify locations.

A single point indicates that the referenced module or software package is in the same directory as the current location. Two points indicate that it is located in the parent directory of the current location, i.e. the directory above. Three dots indicate that it is in the grandparents directory, and so on. If you use a Unix-like operating system, this may be familiar to you!

Suppose you have the same directory structure as before:

└── project
    ├── package1
    │   ├──
    │   └──
    └── package2
        ├── __init__.py
        ├──
        ├──
        └── subpackage1
            └──

You can import the file via package1/:

# package1/

from .module2 import function1

You can import class1 and function2 into package2/file:

# package2/

from . import class1
from .subpackage1.module5 import function2

In the first import statement, a single point means that you are importing class1 from the current package. Remember that importing a package will actually import the package's __init__.py file as a module.

In the second import statement you will use a dot again because subpackage1 it is in the same directory as the current module.

Of course, there is a huge problem with this method, and an error may be reported, as shown below:

ModuleNotFoundError: No module named '__main__.module2'; '__main__' is not a package

This is relative import only works if the parent module has been imported in the current running environment, so use absolute imports as much as possible. See the solution:

Pros and cons of relative import

One obvious advantage of relative imports is that they are very concise. Depending on the current location, they can turn the ridiculously lengthy import statement you saw before into simple things like this:

from …subpackage4.module5 import function6

Unfortunately, relative imports can be confusing, especially for shared projects where directory structures may change. It is not as easy to read as absolute imports, and it is difficult to tell where the import resources are located.

The above is a detailed analysis of absolute import and relative import in Python. For more information about absolute import and relative import in Python, please pay attention to my other related articles!