python
error-handling
importerror
programming
troubleshooting

ModuleNotFoundError What does it mean __main__ is not a package?

Master System Design with Codemia

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

Introduction

The error ModuleNotFoundError: __main__ is not a package occurs when you use a relative import (like from .module import something) inside a script that Python is running directly as the entry point. Python treats directly-executed scripts as the __main__ module, which has no package context, so relative imports cannot be resolved. The fix is to restructure your imports to be absolute, or run the module using python -m package.module instead of python module.py.

The Error

python
1# my_package/utils.py
2def helper():
3    return "I'm a helper"
4
5# my_package/main.py
6from .utils import helper  # Relative import
7
8print(helper())
bash
$ python my_package/main.py
# ModuleNotFoundError: attempted relative import with no known parent package
# Or: __main__ is not a package

Why This Happens

When you run python my_package/main.py, Python sets main.py as the __main__ module. The __main__ module has no parent package, so the dot in from .utils has nowhere to resolve to.

Relative imports use the __package__ attribute to determine the current module's position in the package hierarchy. For directly-executed scripts, __package__ is None, making relative imports impossible.

python
1# When run directly: python main.py
2print(__name__)     # "__main__"
3print(__package__)  # None — no package context
4
5# When run as module: python -m my_package.main
6print(__name__)     # "__main__"
7print(__package__)  # "my_package" — package context exists

Fix 1: Use Absolute Imports

Replace relative imports with absolute imports that use the full package path:

python
1# my_package/main.py
2
3# Instead of:  from .utils import helper
4# Use:
5from my_package.utils import helper
6
7print(helper())
bash
# Run from the directory CONTAINING my_package/
$ python my_package/main.py
# Works if my_package's parent directory is in sys.path

Absolute imports are clearer and work regardless of how the script is executed.

Fix 2: Run with python -m

The -m flag tells Python to run the module within its package context, which enables relative imports:

python
1# my_package/main.py
2from .utils import helper  # Relative import works now
3
4print(helper())
bash
# Run from the directory CONTAINING my_package/
$ python -m my_package.main
# Works — Python sets __package__ = "my_package"

The directory structure must include __init__.py:

 
1project/
2├── my_package/
3│   ├── __init__.py    # Required — marks directory as a package
4│   ├── main.py
5│   └── utils.py
6└── run.py             # Optional external entry point

Fix 3: Create an External Entry Point

Move the entry point outside the package so all internal imports can be relative:

python
1# project/run.py (outside the package)
2from my_package.main import main
3main()
4
5# my_package/main.py
6from .utils import helper
7
8def main():
9    print(helper())
10
11# my_package/utils.py
12def helper():
13    return "I'm a helper"
bash
$ python run.py
# Works — my_package is imported as a package, relative imports resolve

This is the standard pattern for Python applications. The entry point script imports the package rather than being part of it.

Fix 4: Modify sys.path (Last Resort)

python
1# my_package/main.py
2import sys
3import os
4sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
5
6from my_package.utils import helper
7print(helper())

This works but is fragile and not recommended. It hard-codes path assumptions and breaks if the directory structure changes.

Understanding Relative vs Absolute Imports

python
1# Absolute import — full path from project root
2from my_package.utils import helper
3from my_package.sub.module import func
4
5# Relative import — relative to current module's package
6from .utils import helper          # Same package
7from ..other_pkg import something  # Parent package's sibling
8from . import utils                # Import sibling module

Relative imports only work when the module has a package context (__package__ is set). This requires either running with -m or importing the module from another script.

The init.py Requirement

 
1# This structure supports relative imports:
2my_package/
3├── __init__.py        # Can be empty — just marks it as a package
4├── main.py
5├── utils.py
6└── sub/
7    ├── __init__.py    # Also required for sub-packages
8    └── module.py

Without __init__.py, Python 3 still recognizes namespace packages, but relative imports require regular packages with __init__.py files.

Common Pitfalls

  • Running python file.py inside a package directory: This executes the file as __main__ with no package context. Use python -m package.module from the parent directory instead.
  • Missing __init__.py: Without this file, the directory is not a regular package and relative imports fail. Add an empty __init__.py to every package directory.
  • Running from the wrong directory: python -m my_package.main must be run from the directory that contains my_package/, not from inside my_package/.
  • Mixing relative and absolute imports inconsistently: Pick one style per project. Absolute imports are generally preferred because they work regardless of execution context.
  • Using relative imports in top-level scripts: If a file is meant to be run directly (like manage.py or setup.py), never use relative imports in it. Only use relative imports in library/package modules.

Summary

  • The error occurs because directly-executed scripts have no package context for resolving relative imports
  • Use absolute imports (from package.module import func) for the simplest fix
  • Use python -m package.module to run scripts with package context, enabling relative imports
  • Create an external entry point script that imports your package for the cleanest architecture
  • Every package directory needs an __init__.py file for relative imports to work

Course illustration
Course illustration

All Rights Reserved.