---
# === IDENTITY ===
id: software/debugging/python-importerror/2026
canonical_question: "How do I fix ImportError and ModuleNotFoundError in Python?"
aliases:
  - "Python ImportError"
  - "Python ModuleNotFoundError"
  - "No module named Python"
  - "Python cannot import name"
  - "Python import not working"
  - "Python relative import error"
  - "Python circular import"
  - "Python sys.path module not found"
entity_type: software_reference
domain: software > debugging > python_importerror
region: global
jurisdiction: global
temporal_scope: 2020-2026

# === VERIFICATION ===
last_verified: 2026-05-17
confidence: 0.93
version: 2.1
first_published: 2026-02-17

# === TEMPORAL VALIDITY ===
temporal_validity:
  status: stable
  last_breaking_change: "Python 3.14 (Oct 2025) — importlib.load_module() deprecated, use exec_module(); -X importtime=2 added for tracking cached imports; REPL import auto-completion added"
  next_review: 2026-11-13
  change_sensitivity: low

# === CONSTRAINTS ===
constraints:
  - "Always use python -m pip install instead of bare pip install — pip may point to a different Python than python"
  - "Never hack sys.path.insert() in application code — use pyproject.toml + pip install -e . for proper package resolution"
  - "Setting __package__ and __cached__ on modules is deprecated (3.13+) and will stop working in Python 3.15 — set __spec__.parent and __spec__.cached instead"
  - "uv-managed virtual environments do not include pip by default — use uv pip install or uv add instead"
  - "Do not name your Python files after stdlib modules (random.py, email.py, test.py) — this shadows the real module and causes ImportError"

# === SKIP CONDITIONS ===
skip_this_unit_if:
  - condition: "Error is AttributeError after a successful import (module loads but attribute missing)"
    use_instead: "Check the object name in the imported module or inspect module version for API changes"
  - condition: "Error is SyntaxError inside the imported module (not an import problem)"
    use_instead: "Fix the syntax error in the target module file"
  - condition: "Error is a DLL load failure or shared library error on Windows/Linux"
    use_instead: "software/debugging/python-dll-load-failed/2026"

# === AGENT HINTS ===
inputs_needed:
  - key: error_type
    question: "What is the exact error message? (ModuleNotFoundError, ImportError, or the full traceback)"
    type: text
  - key: module_origin
    question: "Is the failing module a third-party package (from PyPI) or your own project module?"
    type: choice
    options: ["Third-party (pip install)", "My own module", "Not sure"]
  - key: environment
    question: "Are you using a virtual environment (venv, conda, uv, poetry)?"
    type: choice
    options: ["venv", "conda", "uv", "poetry", "No virtualenv / system Python", "Not sure"]

# === DISTRIBUTION ===
canonical_source: "https://knowledgelib.io/software/debugging/python-importerror/2026"
suggested_citation: "Source: knowledgelib.io — AI Knowledge Library (verified 2026-05-17)"

# === RELATED UNITS ===
related_kos:
  related_to:
    - id: "software/debugging/python-memory-leaks/2026"
      label: "Python Memory Leaks"
    - id: "software/debugging/docker-container-wont-start/2026"
      label: "Docker Container Won't Start"
  solves:
    - id: "software/debugging/nodejs-econnrefused/2026"
      label: "Node.js ECONNREFUSED (similar debugging methodology)"
  often_confused_with:
    - id: "software/debugging/django-n-plus-1/2026"
      label: "Django N+1 Query Problems (runtime error, not import error)"

# === SOURCES (5-8 authoritative sources) ===
sources:
  - id: src1
    title: "Python — The Import System"
    author: Python Software Foundation
    url: https://docs.python.org/3/reference/import.html
    type: official_docs
    published: 2025-10-01
    reliability: authoritative
  - id: src2
    title: "Python — sys.path and Module Search"
    author: Python Software Foundation
    url: https://docs.python.org/3/library/sys.html#sys.path
    type: official_docs
    published: 2025-10-01
    reliability: authoritative
  - id: src3
    title: "Real Python — Absolute vs Relative Imports in Python"
    author: Real Python
    url: https://realpython.com/absolute-vs-relative-python-imports/
    type: technical_blog
    published: 2025-01-01
    reliability: high
  - id: src4
    title: "Stack Overflow — ImportError: attempted relative import with no known parent package"
    author: Stack Overflow Community
    url: https://stackoverflow.com/questions/16981921/relative-imports-in-python-3
    type: community_resource
    published: 2024-01-01
    reliability: moderate_high
  - id: src5
    title: "Python Packaging User Guide — Installing Packages"
    author: Python Packaging Authority (PyPA)
    url: https://packaging.python.org/en/latest/tutorials/installing-packages/
    type: official_docs
    published: 2025-06-01
    reliability: authoritative
  - id: src6
    title: "DataCamp — Python Circular Import: Causes, Fixes, and Best Practices"
    author: DataCamp
    url: https://www.datacamp.com/tutorial/python-circular-import
    type: technical_blog
    published: 2025-03-01
    reliability: high
  - id: src7
    title: "Python — venv: Creating Virtual Environments"
    author: Python Software Foundation
    url: https://docs.python.org/3/library/venv.html
    type: official_docs
    published: 2025-10-01
    reliability: authoritative
  - id: src8
    title: "What's New In Python 3.13 — Import System Changes"
    author: Python Software Foundation
    url: https://docs.python.org/3/whatsnew/3.13.html
    type: official_docs
    published: 2024-10-07
    reliability: authoritative
  - id: src9
    title: "What's New In Python 3.14 — Import System & importtime"
    author: Python Software Foundation
    url: https://docs.python.org/3/whatsnew/3.14.html
    type: official_docs
    published: 2025-10-07
    reliability: authoritative
  - id: src10
    title: "Pending Removal in Python 3.15 — __package__, __cached__, importlib.load_module()"
    author: Python Software Foundation
    url: https://docs.python.org/3/deprecations/pending-removal-in-3.15.html
    type: official_docs
    published: 2025-10-07
    reliability: authoritative
---

# How to Fix ImportError and ModuleNotFoundError in Python

## TL;DR

- **Bottom line**: `ModuleNotFoundError` (a subclass of `ImportError`) means Python cannot locate the module you're trying to import. The 5 most common causes: (1) package not installed (`pip install`), (2) wrong Python environment/virtualenv, (3) incorrect `sys.path` / project structure, (4) circular imports between modules, (5) name shadowing (your file has the same name as a library).
- **Key tool/command**: `python -c "import sys; print(sys.path)"` shows exactly where Python looks for modules. `pip show package_name` verifies installation location. `python -m pip install package` ensures you install into the correct Python.
- **Watch out for**: Running `pip install` outside your virtualenv — the package goes into the system Python while your code runs in the venv. Always check `which python` / `where python` first. With `uv`, virtual environments do not include `pip` by default.
- **Works with**: Python 3.6+ (ModuleNotFoundError introduced in 3.6). Applies to all frameworks: Django, Flask, FastAPI, scripts, notebooks. Verified against Python 3.14 (released Oct 7, 2025) — adds `-X importtime=2` for tracking cached imports and REPL import auto-completion. [src9]

## Constraints
<!-- Agents: read this section before recommending any action from this unit.
     These are hard constraints that must not be violated. -->

- **Always use `python -m pip install`** instead of bare `pip install` — `pip` may point to a different Python interpreter than `python`, especially on systems with multiple Python versions. [src5]
- **Never hack `sys.path.insert()` in application code** — use `pyproject.toml` + `pip install -e .` for proper package resolution. sys.path hacks break when directory structure changes. [src1, src2]
- **Python 3.13+ deprecates `__package__` and `__cached__`** — setting these module attributes is deprecated and will cease to be set or considered by the import system in **Python 3.15** (originally announced for 3.14 but slipped). Use `__spec__.parent` and `__spec__.cached` instead. [src8, src10]
- **uv-managed virtualenvs do not include pip** — if using the `uv` package manager, use `uv pip install` or `uv add` instead of bare `pip`. Only add pip when required for compatibility (e.g., Jupyter's `%pip` magic). [src5]
- **Do not name files after stdlib modules** — files named `random.py`, `email.py`, `test.py`, `json.py`, `os.py` will shadow the real stdlib module and cause `ImportError`. Python 3.13 now warns about this explicitly. [src1, src8]

## Quick Reference

| # | Cause | Likelihood | Signature | Fix |
|---|---|---|---|---|
| 1 | Package not installed | ~30% of cases | `ModuleNotFoundError: No module named 'package'` | `pip install package` or `python -m pip install package` [src5] |
| 2 | Wrong Python / virtualenv | ~20% of cases | `pip install` succeeds but import still fails | Activate venv: `source venv/bin/activate`; verify: `which python` [src7] |
| 3 | Incorrect `sys.path` / project structure | ~15% of cases | `ModuleNotFoundError` for your own module | Add `__init__.py`, fix project root, or use `pip install -e .` [src1, src2] |
| 4 | Circular import | ~10% of cases | `ImportError: cannot import name 'X' from partially initialized module` | Refactor: move shared code to third module, or use local imports [src6] |
| 5 | Name shadowing (file shadows library) | ~8% of cases | `ImportError: cannot import name 'X' from 'module'` | Rename your file (e.g., `random.py` -> `my_random.py`) [src1, src8] |
| 6 | Relative import outside package | ~6% of cases | `ImportError: attempted relative import with no known parent package` | Run as module: `python -m package.module` instead of `python module.py` [src3, src4] |
| 7 | Missing `__init__.py` | ~4% of cases | `ModuleNotFoundError` for subpackage | Add empty `__init__.py` to directory [src1, src3] |
| 8 | Package name != import name | ~3% of cases | `pip install` succeeds, import name differs | Check PyPI page for correct import name (e.g., `pip install Pillow` -> `import PIL`) [src5] |
| 9 | Python version mismatch | ~2% of cases | Package incompatible with Python version | Check package compatibility; use `python --version` [src5] |
| 10 | IDE / editor path misconfiguration | ~2% of cases | Works in terminal but not in IDE | Set Python interpreter path in IDE settings [src2] |

## Decision Tree

> Full script: [decision-tree.txt](scripts/decision-tree.txt) (25 lines)

```
START
├── Is the module a third-party package (from PyPI)?
│   ├── YES -> Is it installed? (pip show package_name)
│   │   ├── NOT INSTALLED -> pip install package_name [src5]
│   │   └── INSTALLED -> Is it in the right environment?
│   │       ├── Check: which python / where python -> matches venv? [src7]
│   │       │   ├── WRONG PYTHON -> Activate correct venv [src7]
│   │       │   └── CORRECT PYTHON -> Does import name match package name?
│   │       │       ├── NO -> Find correct import name (PyPI docs) [src5]
│   │       │       └── YES -> Check for name shadowing [src8]
│   │       └── IDE using different interpreter? -> Set interpreter in IDE [src2]
│   └── NO -> It's your own module ↓
├── Does the error say "partially initialized module" or "circular import"?
│   ├── YES -> Circular import. Refactor or use local imports [src6]
│   └── NO ↓
├── Does the error say "relative import with no known parent package"?
│   ├── YES -> Run as module: python -m package.module [src3, src4]
│   └── NO ↓
├── Is the module in a subdirectory?
│   ├── YES -> Does the directory have __init__.py? [src1]
│   │   ├── NO -> Add __init__.py
│   │   └── YES -> Is the parent directory in sys.path? [src2]
│   └── NO ↓
├── Using uv? -> uv pip install or uv add (pip not available by default) [src5]
│   └── NO ↓
└── Print sys.path and verify module location
    -> python -c "import sys; print('\n'.join(sys.path))" [src2]
```

## Step-by-Step Guide

### 1. Read the exact error message

Python gives you precise information about what went wrong. Python 3.13+ provides even better error messages, including warnings when your file shadows a stdlib module. [src1, src8]

```python
# ModuleNotFoundError — module doesn't exist in sys.path
ModuleNotFoundError: No module named 'requests'

# ImportError — module exists but the name inside it doesn't
ImportError: cannot import name 'Response' from 'my_module'

# ImportError — circular import
ImportError: cannot import name 'X' from partially initialized module 'Y'

# ImportError — relative import issue
ImportError: attempted relative import with no known parent package

# Python 3.13+ — name shadowing warning (new)
# "module 'random' has no attribute 'randint'" with hint:
# "consider renaming '/home/user/random.py' since it has the same name as the standard library module"
```

**Verify**: Note the exact module name and which of the five patterns your error matches.

### 2. Check if the package is installed

For third-party packages, verify installation first. [src5]

```bash
# Check if installed and where
pip show requests
# Output: Name: requests, Version: 2.32.3, Location: /path/to/site-packages

# List all installed packages
pip list | grep -i requests

# If not installed:
pip install requests

# SAFEST: use python -m pip to ensure correct Python
python -m pip install requests

# For a specific Python version
python3.13 -m pip install requests

# If using uv (pip not available by default in uv environments)
uv pip install requests
# Or better: uv add requests
```

**Verify**: `pip show package_name` shows the package with a `Location` inside your virtualenv's `site-packages`.

### 3. Verify you're in the right Python environment

The most frustrating cause: installing into system Python while running code in a virtualenv (or vice versa). [src7]

```bash
# Check which Python is active
which python    # Linux/macOS
where python    # Windows
# Should point to: /path/to/venv/bin/python (not /usr/bin/python)

# Check which pip matches which Python
python -m pip --version
# pip 24.3 from /path/to/venv/lib/python3.13/site-packages/pip

# Activate virtualenv
# Linux/macOS
source venv/bin/activate

# Windows (PowerShell)
.\venv\Scripts\Activate.ps1

# Windows (cmd)
venv\Scripts\activate.bat

# If using uv
uv venv
source .venv/bin/activate  # Linux/macOS
.\.venv\Scripts\activate   # Windows

# Verify after activation
python -c "import sys; print(sys.executable)"
```

**Verify**: `sys.executable` points to your virtualenv's Python binary.

### 4. Inspect sys.path

Python searches for modules in the directories listed in `sys.path`. [src1, src2]

```python
# Print sys.path to see all search directories
import sys
print('\n'.join(sys.path))

# Check where an imported module actually comes from
import requests
print(requests.__file__)
# /path/to/venv/lib/python3.13/site-packages/requests/__init__.py

# Check if your project root is in sys.path
import os
print(os.getcwd())  # Current working directory
print(os.getcwd() in sys.path)  # Should be True
```

```bash
# Quick check from terminal
python -c "import sys; print('\n'.join(sys.path))"
```

**Verify**: The directory containing your module appears in `sys.path`.

### 5. Fix project structure

Proper Python package structure ensures imports work correctly. [src1, src3]

```
# CORRECT project structure
my_project/
├── pyproject.toml          # or setup.py
├── src/
│   └── my_package/
│       ├── __init__.py     # Makes it a package (can be empty)
│       ├── main.py
│       ├── utils.py
│       └── sub_package/
│           ├── __init__.py # Required for subpackage
│           └── helpers.py
├── tests/
│   ├── __init__.py
│   └── test_main.py
└── venv/
```

```python
# Imports that work with this structure:
from my_package.utils import helper_function
from my_package.sub_package.helpers import some_helper

# For development: install your package in editable mode
# pip install -e .
# This adds your project to sys.path so imports always work
```

**Verify**: Run `python -c "from my_package import main"` from the project root.

### 6. Fix circular imports

Circular imports happen when module A imports from B and B imports from A. [src6]

```python
# PROBLEM: Circular import
# file: models.py
from services import get_user_service   # imports services.py

# file: services.py
from models import User                  # imports models.py -> CIRCULAR!

# FIX 1: Move shared code to a third module
# file: shared.py (new)
class User: ...

# file: models.py
from shared import User

# file: services.py
from shared import User

# FIX 2: Use local (deferred) imports
# file: services.py
def get_user_service():
    from models import User  # Import inside function, not at top level
    return User.objects.get(...)

# FIX 3: Import the module, not the name
# file: services.py
import models  # Import module, not 'from models import User'
def get_user_service():
    return models.User.objects.get(...)
```

**Verify**: `python -c "import models; import services"` works without errors.

### 7. Fix name shadowing

If your file has the same name as a library, Python imports your file instead. Python 3.13 now provides explicit warnings for this. [src1, src8]

```bash
# Check if you're shadowing a module
python -c "import random; print(random.__file__)"
# If it shows YOUR file: /home/user/project/random.py -> NAME CONFLICT!
# Should show: /usr/lib/python3.13/random.py

# Common offenders:
# random.py, email.py, test.py, json.py, os.py, re.py, string.py,
# collections.py, http.py, calendar.py, typing.py
```

**Fix**: Rename your file. Also delete any `.pyc` files or `__pycache__` directories from the old name:

```bash
find . -name "__pycache__" -type d -exec rm -rf {} +
find . -name "*.pyc" -delete
```

**Verify**: `python -c "import random; print(random.__file__)"` points to the stdlib.

## Decision Logic

### If error reads "No module named X" AND `pip show X` shows the package installed
--> Python interpreter mismatch. Run `python -c "import sys; print(sys.executable)"` to see the active interpreter, then `which pip` (Linux/macOS) or `where pip` (Windows). Reinstall with the explicit interpreter: `python -m pip install X`. [src5, src7]

### If error reads "cannot import name 'X' from partially initialized module 'Y'"
--> Circular import. Either (1) extract `X` to a third shared module, (2) move the `from Y import X` line inside the function that uses it, or (3) `import Y` and reference `Y.X` at call time. Do NOT call `importlib.reload()` — it makes the cycle worse. [src6]

### If error reads "attempted relative import with no known parent package"
--> Script is being run as a top-level file, not a package. Run as a module: `python -m package.module` from the project root, OR convert the relative import to absolute (`from package.helpers import X`). [src3, src4]

### If `pip install` succeeded but `import` still fails AND you're using uv
--> The uv-managed virtualenv has no `pip` by default — system pip installed into a different environment. Activate the uv venv (`source .venv/bin/activate`) and reinstall with `uv pip install X` or `uv add X`. [src5]

### If the import works from the terminal but fails in Jupyter / VS Code / PyCharm
--> The IDE is using a different Python interpreter. Check `sys.executable` in a notebook cell or IDE settings; point the IDE to the venv's Python (`./venv/bin/python` or `./.venv/bin/python`). For Jupyter specifically, install `ipykernel` into the venv: `python -m ipykernel install --user --name myenv`. [src2, src7]

### If a third-party module imports fine but `from module import X` raises ImportError
--> Either (a) the package name differs from the import name (e.g. `pip install Pillow` -> `import PIL`, `pip install opencv-python` -> `import cv2`, `pip install scikit-learn` -> `import sklearn`), or (b) your local file shadows the library — run `python -c "import module; print(module.__file__)"` and rename if it points into your project. [src1, src5, src8]

### If running on Python 3.13+ AND your custom import hook sets `module.__package__` or `module.__cached__`
--> Migrate now. Setting these attributes is deprecated in 3.13 and will be ignored in **Python 3.15** (the originally-announced 3.14 removal slipped). Set `module.__spec__.parent` and `module.__spec__.cached` instead. Replace any `importlib.load_module()` calls with `exec_module()`. [src8, src9, src10]

## Code Examples

### Robust import with fallback and diagnostics

> Full script: [robust-import-with-fallback-and-diagnostics.py](scripts/robust-import-with-fallback-and-diagnostics.py) (29 lines)

```python
# Input:  Script needs to run in different environments (some may lack packages)
# Output: Graceful handling of missing imports with helpful error messages
import sys
import importlib
def safe_import(module_name, package_name=None, install_hint=None):
# ... (see full script)
```

### Import debugging utility

> Full script: [import-debugging-utility.py](scripts/import-debugging-utility.py) (73 lines)

```python
# Input:  Can't figure out why an import is failing
# Output: Diagnostic script that pinpoints the problem
import sys
import os
import importlib
# ... (see full script)
```

### Proper package setup with pyproject.toml

```toml
# Input:  Project where imports break when running from different directories
# Output: pyproject.toml that makes imports always work

# pyproject.toml
[build-system]
requires = ["setuptools>=68.0", "wheel"]
build-backend = "setuptools.backends._legacy:_Backend"

[project]
name = "my-project"
version = "0.1.0"
requires-python = ">=3.9"
dependencies = [
    "requests>=2.28",
    "pydantic>=2.0",
]

[project.optional-dependencies]
dev = [
    "pytest>=7.0",
    "ruff>=0.1",
]

[tool.setuptools.packages.find]
where = ["src"]
```

```bash
# Install your project in editable mode:
pip install -e ".[dev]"

# Now imports work from ANYWHERE:
# python -c "from my_package.utils import helper"  <- works
# pytest tests/  <- works (imports resolve correctly)
```

## Anti-Patterns

### Wrong: Installing packages globally

```bash
# BAD — installs into system Python, not your project's venv [src5, src7]
sudo pip install requests
pip install requests  # Which Python? Who knows!
```

### Correct: Use virtualenv and python -m pip

```bash
# GOOD — explicit, uses correct Python [src5, src7]
python -m venv venv
source venv/bin/activate  # or .\venv\Scripts\activate on Windows
python -m pip install requests
```

### Wrong: Hacking sys.path in application code

```python
# BAD — fragile, breaks when directory structure changes [src2]
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'lib'))
sys.path.append('/home/user/my_project/src')
from my_module import something
```

### Correct: Proper package structure with editable install

```bash
# GOOD — works everywhere, no sys.path hacking [src1, src5]
# Create pyproject.toml with [tool.setuptools.packages.find]
pip install -e .

# Now imports just work:
from my_package.my_module import something
```

### Wrong: Running script directly with relative imports

```python
# BAD — running directly breaks relative imports [src3, src4]
# file: my_package/utils.py
from .helpers import format_data  # Relative import

# Running: python my_package/utils.py
# Error: ImportError: attempted relative import with no known parent package
```

### Correct: Run as module

```bash
# GOOD — run as module so Python knows the package context [src3, src4]
python -m my_package.utils

# Or use absolute imports instead:
from my_package.helpers import format_data  # Absolute import
```

## Common Pitfalls

- **`pip install` vs `python -m pip install`**: Just `pip` might point to a different Python than `python`. Always use `python -m pip install` to guarantee you install into the Python you're actually running. [src5]
- **Package name != import name**: Many packages have different pip and import names: `Pillow` -> `PIL`, `opencv-python` -> `cv2`, `beautifulsoup4` -> `bs4`, `scikit-learn` -> `sklearn`, `PyYAML` -> `yaml`. Check the PyPI page. [src5]
- **Missing `__init__.py`**: Python 3 has namespace packages (no `__init__.py` needed), but regular packages still need it for most use cases. Add an empty `__init__.py` to every directory you want as a package. [src1, src3]
- **Name shadowing with `test.py`**: A file named `test.py` shadows Python's built-in `test` module and can break `unittest`. Other common shadows: `email.py`, `random.py`, `json.py`, `string.py`. Python 3.13 now warns about this explicitly. [src1, src8]
- **Stale `.pyc` / `__pycache__`**: After renaming or moving files, old bytecode cache may confuse imports. Delete with `find . -name "__pycache__" -exec rm -rf {} +`. [src1]
- **Jupyter notebook path issues**: Notebooks run from the notebook's directory, not your project root. Add the project root: `sys.path.insert(0, '/path/to/project')` or use `%cd /path/to/project`. [src2]
- **uv environments lack pip**: If you created your virtualenv with `uv`, `pip` is not installed by default. Use `uv pip install` or `uv add` instead. Only add pip for Jupyter `%pip` compatibility. [src5]
- **Python 3.13 `__package__` deprecation**: Setting `__package__` or `__cached__` on a module is deprecated in 3.13 and will stop being respected by the import system in **Python 3.15** (the originally-announced 3.14 removal slipped — they still work in 3.14 but emit `DeprecationWarning`). Use `__spec__.parent` and `__spec__.cached` instead. [src8, src9, src10]
- **`importlib.load_module()` is deprecated (3.14+)**: Replace any custom loader code calling `load_module()` with `exec_module()`. Pending removal target is 3.15. [src9, src10]

## Diagnostic Commands

> Full script: [diagnostic-commands.sh](scripts/diagnostic-commands.sh) (42 lines)

```bash
# Check which Python is active
which python          # Linux/macOS
where python          # Windows
python --version
# Check if in virtualenv
# ... (see full script)
```

## Version History & Compatibility

| Version | Behavior | Key Changes |
|---|---|---|
| Python 3.14 (Oct 2025) | `ModuleNotFoundError` (current) | `-X importtime=2` tracks cached imports (shows `cached` instead of timings); REPL import auto-completion (`import co<Tab>`); `importlib.load_module()` deprecated — use `exec_module()`; `__package__`/`__cached__` removal slipped to Python 3.15 [src9, src10] |
| Python 3.13 (Oct 2024) | `ModuleNotFoundError` (enhanced) | Better name-shadowing warnings; `__package__`/`__cached__` deprecated; `from .__future__` no longer triggers future statements [src8] |
| Python 3.12 | `ModuleNotFoundError` (standard) | Improved error messages with suggestions for similar module names; `pkgutil.find_loader()` deprecated [src1] |
| Python 3.11 | `ModuleNotFoundError` | Exception groups; better tracebacks for import errors [src1] |
| Python 3.10 | `ModuleNotFoundError` | `importlib.metadata` improvements; better error messages [src1] |
| Python 3.9 | `ModuleNotFoundError` | `importlib.resources` updates [src1] |
| Python 3.6 | `ModuleNotFoundError` introduced | New subclass of `ImportError` for missing modules [src1] |
| Python 3.3 | Namespace packages | `__init__.py` no longer required for namespace packages [src1] |
| Python 2.x | `ImportError` only | No `ModuleNotFoundError`; different import semantics [src1] |

## When to Use / When Not to Use

| Use When | Don't Use When | Use Instead |
|---|---|---|
| Error says `ModuleNotFoundError` or `ImportError` | Error is `AttributeError` after successful import | Check the object name in the module |
| `import` statement fails | Error is `SyntaxError` in the imported module | Fix syntax in the target module |
| Package installs but import still fails | Error is `PermissionError` during import | Check file permissions |
| Error mentions "partially initialized module" | Error is `ValueError` from module code | Debug the module's runtime logic |
| Module works in terminal but not in IDE | Error is `DLL load failed` or shared library missing | Reinstall package with binary deps |

## Important Caveats

- `ModuleNotFoundError` is a subclass of `ImportError`. Catching `ImportError` will also catch `ModuleNotFoundError`. Use the more specific type when you only want to handle missing modules.
- Namespace packages (PEP 420, Python 3.3+) allow packages without `__init__.py`, but only for specific use cases like namespace packages shared across multiple distributions. For regular projects, always include `__init__.py`.
- `pip install --user` installs to `~/.local/lib/pythonX.Y/site-packages/`, which may not be in `sys.path` for all Python invocations (especially in virtualenvs or with `sudo`).
- In Docker containers, you're usually running as root — there's no virtualenv needed. But if your Dockerfile uses a multi-stage build, ensure packages are installed in the final stage, not just the build stage.
- `importlib.reload(module)` can re-import a module but won't fix circular imports — it may make them worse by re-triggering the import cycle.
- Python 3.15 (upcoming) will stop respecting `__package__` and `__cached__` module attributes — the originally-announced 3.14 removal slipped one release. Code that sets these during import will silently lose effect. Audit any custom import hooks and set `__spec__.parent` / `__spec__.cached` instead. [src10]
- Python 3.14 (released Oct 7, 2025) keeps `__package__` and `__cached__` working but emits `DeprecationWarning`. `importlib.load_module()` is also deprecated in 3.14 — replace with `exec_module()`. [src9, src10]
- Some packages broke compatibility with Python 3.14 early releases due to missing built-in modules (e.g., pandas wheels lagged). Always check package compatibility before upgrading Python — many issues resolve within a few months of a major release.

## Related Units
<!-- Generated from related_kos frontmatter -->

- [Python Memory Leaks](/software/debugging/python-memory-leaks/2026)
- [Node.js ECONNREFUSED](/software/debugging/nodejs-econnrefused/2026)
- [Django N+1 Query Problems](/software/debugging/django-n-plus-1/2026)
- [Docker Container Won't Start](/software/debugging/docker-container-wont-start/2026)
