Python
Module Import
Programming Error
Troubleshooting
Python Modules

Can't import my own modules in Python

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

When Python says ModuleNotFoundError: No module named 'mymodule', it means mymodule.py is not in any directory Python is searching. Python looks in the current directory, installed packages, and directories listed in sys.path. The fix is usually one of: running from the correct directory, adding an __init__.py to make a package, installing your project with pip install -e ., or adjusting sys.path.

How Python Finds Modules

When you write import mymodule, Python searches these locations in order:

python
1import sys
2print(sys.path)
3# ['',                                    # Current directory
4#  '/usr/lib/python3.11',                 # Standard library
5#  '/usr/lib/python3.11/lib-dynload',
6#  '/home/user/.local/lib/python3.11/site-packages',  # pip packages
7#  '/usr/lib/python3.11/site-packages']

The empty string '' means the current working directory (where you ran python), not the directory of the script file.

Fix 1: Run from the Correct Directory

 
project/
    main.py
    utils.py
python
# main.py
import utils  # Works if you run from project/
bash
1# WORKS — current directory is project/
2cd project
3python main.py
4
5# FAILS — current directory is home, utils.py is not here
6cd ~
7python project/main.py
8# ModuleNotFoundError: No module named 'utils'

Fix 2: Create a Package with init.py

 
1project/
2    main.py
3    mypackage/
4        __init__.py      # Makes mypackage a Python package
5        helpers.py
6        models.py
python
# main.py
from mypackage import helpers
from mypackage.models import User

__init__.py can be empty — its presence tells Python that the directory is a package. Without it, Python treats the directory as a regular folder and cannot import from it.

Fix 3: Use Relative Imports (Within a Package)

 
1mypackage/
2    __init__.py
3    module_a.py
4    module_b.py
5    subpackage/
6        __init__.py
7        module_c.py
python
1# module_b.py — importing from the same package
2from . import module_a
3from .module_a import some_function
4
5# subpackage/module_c.py — importing from parent package
6from .. import module_a
7from ..module_a import some_function

Relative imports use dots: . for the current package, .. for the parent. They only work inside packages (directories with __init__.py), not in standalone scripts.

Fix 4: Install Your Project with pip install -e

The best approach for projects with multiple modules:

 
1myproject/
2    setup.py    # or pyproject.toml
3    mypackage/
4        __init__.py
5        utils.py
6        models.py
python
1# setup.py
2from setuptools import setup, find_packages
3
4setup(
5    name='myproject',
6    packages=find_packages(),
7)
bash
1# Install in editable mode — changes take effect immediately
2pip install -e .
3
4# Now import from anywhere
5python -c "from mypackage import utils"  # Works from any directory

Or with pyproject.toml:

toml
1[build-system]
2requires = ["setuptools"]
3build-backend = "setuptools.backends._legacy:_Backend"
4
5[project]
6name = "myproject"
7version = "0.1.0"

Fix 5: Add to sys.path (Quick Fix)

python
1import sys
2import os
3
4# Add the parent directory to sys.path
5sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
6
7from mypackage import utils

Or set the PYTHONPATH environment variable:

bash
export PYTHONPATH="/path/to/project:$PYTHONPATH"
python some_script.py

This works but is fragile. Prefer pip install -e . for anything beyond quick scripts.

Fix 6: Use python -m to Run Modules

bash
1# Instead of running the file directly:
2python mypackage/main.py          # sys.path includes mypackage/, not project/
3
4# Run as a module:
5python -m mypackage.main          # sys.path includes project/

python -m adds the current directory to sys.path and treats the argument as a module path, which correctly resolves package imports.

Debugging Import Problems

python
1import sys
2
3# 1. Check where Python is looking
4print(sys.path)
5
6# 2. Check if the module file exists where you think
7import os
8print(os.path.exists('/path/to/mymodule.py'))
9
10# 3. Check if Python can find the module
11import importlib.util
12spec = importlib.util.find_spec('mymodule')
13print(spec)  # None means not found
14
15# 4. Check which file was actually imported
16import mymodule
17print(mymodule.__file__)  # Shows the exact file path

Common Project Structures

 
1# Flat structure (small projects)
2project/
3    main.py
4    utils.py
5    config.py
6
7# Package structure (medium projects)
8project/
9    setup.py
10    myapp/
11        __init__.py
12        main.py
13        utils.py
14        models/
15            __init__.py
16            user.py
17
18# src layout (recommended for libraries)
19project/
20    pyproject.toml
21    src/
22        mylib/
23            __init__.py
24            core.py
25    tests/
26        test_core.py

Common Pitfalls

  • Naming conflicts: If your module is named email.py or json.py, Python imports the standard library module instead of yours. Never name your files after standard library modules.
  • Missing __init__.py: Without __init__.py, a directory is not a package. Python 3 has "namespace packages" (implicit packages without __init__.py), but they behave differently and can cause confusion.
  • Running from the wrong directory: sys.path[0] is the directory of the script being run, not the directory you typed cd into. Use python -m or pip install -e . to avoid this.
  • Virtual environment not activated: If you installed your module in a virtualenv but forgot to activate it, Python uses the system Python which does not have your module.
  • Circular imports: Module A imports Module B, which imports Module A. Python raises ImportError or AttributeError on the partially-loaded module. Break the cycle by moving the import inside a function or restructuring the code.

Summary

  • Python searches sys.path for modules — the current directory is included by default
  • Create __init__.py files to make directories into importable packages
  • Use pip install -e . to install your project in development mode (best approach)
  • Use python -m mypackage.module instead of python mypackage/module.py
  • Avoid naming files after standard library modules (no json.py, email.py, etc.)
  • Debug with sys.path, importlib.util.find_spec(), and module.__file__

Course illustration
Course illustration

All Rights Reserved.