TraceDynamics
Python

ModuleNotFoundError: No module named 'x' — 5 Causes and Fixes

Python says No module named 'x' even though you installed it? Find which of 5 causes you have — wrong interpreter, wrong package name, sys.path — and fix it.

On this page
  1. Diagnose it in 30 seconds
  2. Cause 1: The package is installed in a different Python
  3. Cause 2: The import name is not the package name
  4. Cause 3: You ran a script from a subfolder
  5. Cause 4: Your tool is not using the Python you think
  6. Cause 5: A typo, or a module that was renamed
  7. Confirm the fix
  8. Stop it happening again

You installed the package. You run your script. Python answers:

Output
Traceback (most recent call last):
  File "<string>", line 1, in <module>
    import requests
ModuleNotFoundError: No module named 'requests'

The message is accurate and unhelpful. It means Python searched every folder on its import path and found no module with that name. It does not tell you why, and "I already installed it" is true in most of the cases below. The problem is almost never the package. It is which Python is running, what the package is called, or where Python is looking.

Diagnose it in 30 seconds#

Run these three commands with the same python you use to run your code:

Shell
python -c "import sys; print(sys.executable)"
python -m pip --version
python -c "import importlib.util as u; print(u.find_spec('requests'))"

On a fresh virtual environment with nothing installed, the last line prints None. After installing, it prints a module spec instead. The first two lines tell you which Python and which pip you are talking to. If you have ever been confused about this error, one of those paths was not what you assumed.

Cause 1: The package is installed in a different Python#

This is the most common cause. Most machines have several Pythons: the system one, one from Homebrew or python.org, one per virtual environment, one inside your editor. A bare pip install can target a different one from the python you run.

The reliable habit is to tie the two together:

Shell
python -m pip install requests
python -c "import requests; print(requests.__version__)"

python -m pip runs pip as a module of that exact interpreter, so the package lands where that interpreter will look. Inside an activated virtual environment, which python and which pip should both point into the environment's bin folder:

Output
/tmp/tdlab/c/bin/python
/tmp/tdlab/c/bin/pip

If which pip points somewhere else, that is your bug. Activate the environment, or just use python -m pip and stop worrying about it.

Cause 2: The import name is not the package name#

What you pip install and what you import are often different words:

You install You import
beautifulsoup4 bs4
pillow PIL
pyyaml yaml
scikit-learn sklearn
opencv-python cv2

Installing under the import name is a classic mistake, and it fails in different ways. When we tried it on Python 3.14:

  • pip install PIL, pip install yaml and pip install cv2 all stop with No matching distribution found.
  • pip install sklearn fails to build; install scikit-learn instead.
  • pip install bs4 actually works, because PyPI's bs4 is a small shim that pulls in beautifulsoup4. It is harmless, but depend on beautifulsoup4 directly.

After installing the correct names, the imports resolve:

Output
PIL 12.3.0 | yaml 6.0.3

Cause 3: You ran a script from a subfolder#

This one hits project layouts like this:

Output
proj/
  mypkg/
    __init__.py
    util.py
  scripts/
    run.py        <- from mypkg.util import hello

Run python scripts/run.py from the project root and it fails, even though mypkg is right there:

Output
    from mypkg.util import hello
ModuleNotFoundError: No module named 'mypkg'

The reason: when you run a script, Python puts the script's own folder at the front of the import path, not your current directory. You can see it:

Output
/private/tmp/tdlab/proj/scripts

proj/ is not on the path, so mypkg is invisible. There are three fixes, in order of how good they are. For a related variant of this problem, see importing from a parent directory in Python.

Run it as a module from the project root. Python then puts the current directory on the path:

Shell
python -m scripts.run

Set PYTHONPATH for a quick one-off:

Shell
PYTHONPATH=. python scripts/run.py

Install your project in editable mode, which is the right answer for anything you will keep. With a minimal pyproject.toml:

TOML
[project]
name = "mypkg"
version = "0.1"

[tool.setuptools]
packages = ["mypkg"]
Shell
python -m pip install -e .

All three printed hi in our test. Editable install is the one that keeps working from any folder, in tests, and in your editor.

Cause 4: Your tool is not using the Python you think#

If the import works in your terminal but fails somewhere else, the "somewhere else" is using a different interpreter. Typical culprits are an editor with its own interpreter setting, a Jupyter kernel, a cron job, a systemd service, or a Docker image.

The fix is the same trick every time: print the interpreter at the top of the failing script.

Python
import sys
print(sys.executable)

Then make the tool use the one you installed into. In an editor, that is its "select interpreter" setting. In a notebook, install from inside the notebook so it targets the kernel's Python. In cron or systemd, call the environment's Python by its absolute path rather than relying on PATH, because those environments start with almost nothing on it.

Cause 5: A typo, or a module that was renamed#

Check the boring things last but do check them. Module names are case-sensitive on most systems. And code written for Python 2 uses names that no longer exist: Queue became queue, ConfigParser became configparser, and urllib2 was folded into urllib.request. If the "module" is one of those, no pip install will help; change the import.

If the install itself is what fails, that is a different error with different causes. See the setup.py bdist_wheel error.

Confirm the fix#

Before you close the terminal, check all three of these in the environment where the failure happened:

  1. python -c "import sys; print(sys.executable)" shows the interpreter you meant.
  2. python -m pip show <package> reports a Location inside that interpreter's site-packages.
  3. The import runs with no traceback.

Stop it happening again#

  • Always install with python -m pip, never bare pip.
  • One virtual environment per project, created with python -m venv .venv.
  • Record dependencies in requirements.txt or pyproject.toml, so a fresh environment is one command, not a memory test.
  • Install your own code with pip install -e . instead of fighting sys.path.

More fixes for common Python errors are in the Python section.

Advertisement
esc

↑↓ navigate↵ openesc close