Skip to content

How to Import Modules From Another Folder in Python

Learn how to import Python modules from different directories using sys.path, PYTHONPATH, importlib, or proper package structures to resolve ModuleNotFoundError in multi-folder projects.

When working on large Python projects, your code is often organized across multiple directories. You may need to import a module that lives in a completely different folder from your current script. By default, Python only searches a limited set of directories for modules, so importing from arbitrary locations requires some configuration.

In this guide, you will learn multiple methods to import Python modules from another folder, understand how Python's module search path works, and discover best practices to keep your imports clean and maintainable.

Understanding Python's Module Search Path

Before importing from another folder, it helps to understand where Python looks for modules. When you write import module_name, Python searches these locations in order:

  1. The directory containing the current script.
  2. Directories listed in the PYTHONPATH environment variable.
  3. The default installation-dependent directories (for example, site-packages).

All of these paths are stored in the sys.path list:

import sys

for path in sys.path:
    print(path)

If your target module's folder is not in any of these paths, the import will fail with a ModuleNotFoundError.

Setting Up the Example

For all the methods below, assume the following project structure:

Desktop/
├── Task/
│   └── modules/
│       └── module0.py
└── Projects/
    └── ImportModule/
        └── main.py

The module we want to import (module0.py) contains:

def run():
    print("Module 0 imported successfully")

Our goal is to import module0 from main.py, even though they are in completely different directories.

Method 1: Using sys.path.insert() or sys.path.append()

The most common approach is to programmatically add the target folder to Python's module search path at runtime using sys.path.

Using sys.path.insert()

sys.path.insert(0, path) adds the directory at the beginning of the search path, giving it the highest priority:

import sys

sys.path.insert(0, "C:\\Users\\tom\\Desktop\\Task\\modules")

import module0

module0.run()

Output:

Module 0 imported successfully

Using sys.path.append()

sys.path.append(path) adds the directory at the end of the search path:

import sys

sys.path.append("C:\\Users\\tom\\Desktop\\Task\\modules")

import module0

module0.run()

Output:

Module 0 imported successfully

Difference Between insert and append

Method Priority Use When
sys.path.insert(0, path) Highest, searched first You want your module to take precedence over any same-named module in other paths
sys.path.append(path) Lowest, searched last You want standard library and installed packages to take precedence

Method 2: Using the PYTHONPATH Environment Variable

Instead of modifying sys.path inside your code, you can set the PYTHONPATH environment variable before running your script. Python automatically adds all directories listed in PYTHONPATH to sys.path.

Setting PYTHONPATH on Windows

set PYTHONPATH=C:\Users\tom\Desktop\Task\modules
python main.py

Setting PYTHONPATH on macOS/Linux

export PYTHONPATH=/home/tom/Desktop/Task/modules
python main.py

With PYTHONPATH set, your script needs no path manipulation at all:

import module0

module0.run()

Output:

Module 0 imported successfully

Method 3: Using importlib for Dynamic Imports

When you need to import a module dynamically at runtime (for example, based on user input or configuration), use Python's importlib module along with spec_from_file_location:

main.pypython
import importlib.util

module_path = "C:\\Users\\tom\\Desktop\\Task\\modules\\module0.py"

spec = importlib.util.spec_from_file_location("module0", module_path)

module0 = importlib.util.module_from_spec(spec)

spec.loader.exec_module(module0)

module0.run()

Output:

Module 0 imported successfully

This method is particularly useful when:

  • The module path is determined at runtime.
  • You want to load a specific file without affecting sys.path globally.
  • You are building a plugin system that loads modules from arbitrary locations.

Method 4: Using Packages with __init__.py

If you control the project structure, the cleanest approach is to organize your code as a proper Python package. Add an __init__.py file (can be empty) to each directory that should be treated as a package:

MyProject/
├── main.py
├── utils/
│   ├── __init__.py
│   └── helpers.py
└── core/
    ├── __init__.py
    └── engine.py
def greet():
    print("Hello from helpers!")
from utils.helpers import greet

greet()

Output:

Hello from helpers!

Common Mistakes and How to Fix Them

Mistake 1: Forgetting __init__.py in Package Directories

mypackage/
    module1.py      # No __init__.py!
from mypackage import module1

Fix: Add an __init__.py file (even an empty one) to the directory:

mypackage/
    __init__.py     # Makes it a package
    module1.py

Mistake 2: Circular Imports

If module_a.py imports from module_b.py and module_b.py imports from module_a.py, you get a circular import error:

from module_b import function_b

from module_a import function_a

Fix: Restructure your code to eliminate the cycle, or move the import inside the function that needs it:

def some_function():
    from module_a import function_a
    function_a()

Mistake 3: Modifying sys.path After the Import Statement

import module0

import sys
sys.path.insert(0, "/path/to/modules")

Fix: Always modify sys.path before the import:

import sys
sys.path.insert(0, "/path/to/modules")

import module0

Conclusion

Python provides multiple ways to import modules from another folder, each suited to different scenarios.

  • For quick prototyping, sys.path.insert() or sys.path.append() are the simplest options.
  • For environment-level configuration, PYTHONPATH keeps your code clean by externalizing path management. For dynamic or plugin-based loading, importlib offers maximum flexibility.
  • For production projects, structuring your code as a proper package with __init__.py files is the most maintainable and professional approach. Whichever method you choose, avoid hardcoding absolute paths and prefer relative, portable path construction using pathlib or os.path.
Navigation