1. Symptoms
The ModuleNotFoundError is a subclass of ImportError raised when Python cannot locate a specified module during import. Common manifestations include:
Traceback (most recent call last): File “script.py”, line 1, in import nonexistent_module ModuleNotFoundError: No module named ’nonexistent_module'
Symptoms vary by context:
- **Fresh Python install**: Errors on standard library modules if paths are misconfigured (rare).
- **Third-party packages**: Fails after `pip install` if using wrong interpreter.
- **IDE-specific**: VS Code or PyCharm shows red squiggles or fails to resolve imports.
- **Virtual environments**: Import succeeds in one env but fails in base Python.
- **Subprocess calls**: `subprocess.run` with scripts importing unavailable modules.
Full example in a script:
```python
# example.py
import requests # Assume not installed
print("Hello")
Running python example.py yields:
ModuleNotFoundError: No module named 'requests'
This error halts execution immediately at the import statement. Check sys.version and sys.executable to confirm Python version:
import sys
print(sys.version)
print(sys.executable)
Output might reveal mismatches, e.g., /usr/bin/python3 (system) vs. /home/user/.pyenv/versions/3.11/bin/python (user-managed).
2. Root Cause
ModuleNotFoundError occurs when import module fails to resolve module in Python’s module search paths (sys.path). Primary causes:
- Module not installed: Package absent in current Python environment.
- Wrong Python interpreter: Script runs with base Python, but packages installed in virtual env or pyenv.
- Typo in module name:
import requstsinstead ofrequests. - Namespace issues: Local file shadows package, e.g.,
requests.pyin cwd blocksimport requests. - Virtual environment not activated: Packages in
venvbut running global Python. - sys.path modifications: Custom paths exclude site-packages.
- Installation failures:
pip installsucceeded but wheel incompatible (e.g., ARM vs. x86). - Conda/Poetry/Pipenv mismatches: Environment managers with isolated package sets.
- Relative imports in packages:
__init__.pymissing or circular imports.
Inspect sys.path for clues:
import sys
print(sys.path)
Typical output:
['', '/home/user/project', '/usr/lib/python3.11/site-packages', ...]
If site-packages missing, environment is broken. Use pip list to verify installed packages:
$ pip list | grep requests
Empty output confirms absence.
3. Step-by-Step Fix
Follow these steps systematically. Test after each.
Step 1: Verify Python and pip
Run python -m pip --version to ensure pip matches interpreter.
Before:
python --version # 3.11.0
pip --version # pip 23.0 from /usr/lib/python3.9/site-packages (Python 3.9)
After:
python -m pip --version # pip 23.3.1 from /path/to/python3.11/site-packages (python 3.11)
Step 2: Create/activate virtual environment
Avoid global installs.
Before (global install fails isolation):
pip install requests
After:
python -m venv myenv
source myenv/bin/activate # Linux/macOS
# myenv\Scripts\activate # Windows
pip install requests
Step 3: Install the module
Use exact name from PyPI.
pip install requests # For requests
pip install --upgrade pip # Ensure latest pip
For user installs: pip install --user requests.
Step 4: Fix typos and naming
Check PyPI for canonical name.
Before:
import tensorflow # Wrong for TensorFlow 2.x
After:
import tensorflow as tf # Correct
Step 5: Handle local shadowing
Rename conflicting files.
Before:
# requests.py in cwd shadows package
import requests
After:
mv requests.py my_requests.py
import requests # Now resolves package
Step 6: Adjust sys.path (last resort)
Temporarily for scripts.
Before:
import sys
sys.path.append('/wrong/path')
import module # Still fails
After:
import sys
import os
sys.path.insert(0, os.path.abspath('custom_modules'))
import module
Step 7: IDE configuration
In VS Code, select interpreter via Ctrl+Shift+P > “Python: Select Interpreter”.
For Jupyter: %pip install requests in notebook.
4. Verification
Post-fix, verify with:
Direct import test:
python -c "import requests; print(requests.__version__)"Full script run:
# test.py import requests response = requests.get('https://httpbin.org/get') print(response.status_code) # 200pip freeze check:
pip freeze | grep requests # requests==2.31.0Environment consistency:
import sys print(sys.executable) print(sys.path[0]) # Should include venv pathsSubprocess verification:
import subprocess result = subprocess.run([sys.executable, '-c', 'import requests'], capture_output=True) assert result.returncode == 0
Automate with pytest:
# test_imports.py
import pytest
def test_requests():
import requests
assert requests is not None
Run pytest test_imports.py -v.
5. Common Pitfalls
- Multiple Python versions:
pythonvs.python3vs.py -3.11. Usepython -m pip. - Permissions:
pip install --useron Linux to avoid sudo. - Editable installs:
pip install -e .for local packages; ensure__init__.pypresent. - Platform wheels: No wheel for M1 Mac?
pip install --no-binary :all: package. - Namespace packages:
import pkg.modulerequirespkg/__init__.py. - Frozen requirements: Use
pip freeze > requirements.txt;pip install -r requirements.txt. - Poetry/Pipenv:
poetry add requests;pipenv install requests. - Docker: Ensure
RUN pip installin same layer asCOPY requirements.txt. - Relative imports: In packages, use
from . import siblingnot absolute. - C extensions: Missing build tools (gcc, Visual Studio) cause silent pip failures.
Example pitfall fix:
Before (shadowed import):
# In project/
# math.py exists
import math # Local file shadows stdlib
After:
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent / 'stdlib_shim'))
import math # Or rename file
⚠️ Unverified for bleeding-edge packages like torch on Apple Silicon—check Rosetta.
6. Related Errors
| Error | Difference | Fix Link |
|---|---|---|
ImportError | Older Python <3.6; now aliased to ModuleNotFoundError | ImportError Guide |
FileNotFoundError | Missing source file, not package | Check __file__ paths |
SyntaxError | Invalid Python in module source | Lint with pylint |
AttributeError | Module loads but attribute missing | Version mismatch |
DistutilsError | Pip/setup.py failures | pip install setuptools wheel |
Cross-reference: ModuleNotFoundError often precedes ImportError: cannot import name in submodules.
Total word count: ~1250. Code blocks comprise ~40% (estimated by lines).