# How to Fix ModuleNotFoundError: No Module Named 'package'


`ModuleNotFoundError: No module named 'requests'` means the interpreter that ran your code could not find that module on its import path. The module is usually installed somewhere, just not in the environment Python used, which is why `pip install` can report success and the import still fails.

{{< callout type="info" >}}
**Quick fix:** run your code through [uv](https://pydevtools.com/handbook/reference/uv.md) with `uv run python app.py` instead of `python app.py`. `uv run` selects your project's environment, so the packages you added with `uv add` are the packages your code sees. If it still fails, the diagnostic under [Run one command to identify the cause](#run-one-command-to-identify-the-cause) names which of the five causes you have. New to uv? [Getting started with uv](https://pydevtools.com/handbook/tutorial/getting-started-with-uv.md) covers installing it.
{{< /callout >}}

## Run one command to identify the cause

Substitute the module name from your traceback for `requests` and run this:

```bash
python3 -c "import sys, importlib.util as u; s = u.find_spec('requests'); print(sys.executable); print(s.origin if s else 'NOT FOUND')"
```

Use `python3`, not `python`. A bare `python` is often absent on macOS and many Linux distributions.
```powershell
py -c "import sys, importlib.util as u; s = u.find_spec('requests'); print(sys.executable); print(s.origin if s else 'NOT FOUND')"
```

Use the `py` launcher. On Windows, `python` is frequently a Microsoft Store alias that opens the Store instead of running Python.
Use the top-level name only. For a traceback reading `No module named 'email.mime'`, pass `email`, not `email.mime`. A dotted name makes `find_spec` import the parent package and raise instead of answering.

The first line names the interpreter that just ran. The second gives the file it would import, or `NOT FOUND`:

```console
$ python3 -c "import sys, importlib.util as u; s = u.find_spec('requests'); print(sys.executable); print(s.origin if s else 'NOT FOUND')"
/Users/you/.local/bin/python3
NOT FOUND
```

Now run the same line through `uv run`, which selects your project's environment:

```console
$ uv run python -c "import sys, importlib.util as u; s = u.find_spec('requests'); print(sys.executable); print(s.origin if s else 'NOT FOUND')"
/tmp/demo/.venv/bin/python3
/tmp/demo/.venv/lib/python3.14/site-packages/requests/__init__.py
```

The two runs pick different interpreters, so they give different answers. Read your own output against these five cases:

- **The module resolves under one interpreter but not the other.** You launched the wrong Python. Point pip and python at the same interpreter.
- **`NOT FOUND` everywhere, and the module is a third-party package.** Nothing installed it here, or the import name differs from the name you installed.
- **`NOT FOUND` everywhere, and the module is your own code.** Your package is not importable yet.
- **A path that lands in your project directory rather than `site-packages`.** A local file is shadowing the real module.
- **The error only happens in a notebook.** The kernel is running in a different environment than your shell.

## Fix the error when the package is already installed

The most common version of this error is not a missing package. It is two Pythons on one machine, one holding the package and one running your code. Most systems carry several:

```console
$ which -a python3
/Users/you/.local/bin/python3
/opt/homebrew/bin/python3
/usr/bin/python3
```

A bare `pip` belongs to exactly one of those. Ask a specific interpreter what it has instead:

```bash
python3 -m pip show requests
```
```powershell
py -m pip show requests
```
The `-m` form runs pip from the interpreter you just named, so the answer applies to that Python rather than whichever one owns the `pip` on your `PATH`. Install the same way and the package lands where your code will look for it.

Better still, keep each project in its own [virtual environment](https://pydevtools.com/handbook/explanation/what-is-a-virtual-environment.md) so there is only one candidate:

```bash
python3 -m venv .venv
source .venv/bin/activate
python -m pip install requests
```
```powershell
py -m venv .venv
.venv\Scripts\activate
python -m pip install requests
```
Inside an activated environment the diagnostic reports the environment's own interpreter and finds the package:

```console
$ python -c "import sys, importlib.util as u; s = u.find_spec('requests'); print(sys.executable); print(s.origin if s else 'NOT FOUND')"
/tmp/pipway/.venv/bin/python
/tmp/pipway/.venv/lib/python3.13/site-packages/requests/__init__.py
```

[uv](https://pydevtools.com/handbook/reference/uv.md) collapses these steps: `uv add requests` creates the environment, installs the package, and records the dependency, and `uv run` always launches the matching interpreter. See [how to create and use a virtual environment with venv](https://pydevtools.com/handbook/how-to/how-to-create-and-use-a-python-virtual-environment-with-venv.md) for the manual workflow.

Editors keep their own interpreter setting, which reproduces this error inside the editor while the terminal works. In VS Code, open the Command Palette and run `Python: Select Interpreter`, then pick the `.venv` in your project. PyCharm keeps the same setting under its project interpreter. For the equivalent problem in an AI coding agent, which shells out per command and does not inherit an activated environment, see [how to configure Claude Code to use virtual environments](https://pydevtools.com/handbook/how-to/how-to-configure-claude-code-to-use-virtual-environments.md).

## Install the package, or correct the import name

When the module is missing from every interpreter you try, list what the environment holds:

```console
$ uv pip list
Package            Version
------------------ ---------
certifi            2026.7.22
charset-normalizer 3.4.9
idna               3.18
requests           2.34.2
urllib3            2.7.0
```

Add it to the project so uv records the dependency in `pyproject.toml`:

```bash
uv add requests
```

Check that you are importing the right name. The name you install and the name you import are frequently different, and a wrong guess produces this same error:

```console
$ uv run --with scikit-learn python -c "import scikit_learn"
ModuleNotFoundError: No module named 'scikit_learn'

$ uv run --with scikit-learn python -c "import sklearn; print(sklearn.__version__)"
1.9.0
```

`scikit-learn` installs but `sklearn` imports, and `PyYAML` installs but `yaml` imports. Once a package is installed, the environment can report the mapping:

```console
$ uv run --with scikit-learn python -c "from importlib.metadata import packages_distributions as p; print(p().get('sklearn'))"
['scikit-learn']
```

[Distribution package vs import package](https://pydevtools.com/handbook/explanation/distribution-package-vs-import-package.md) explains why the two names drift apart.

## Make your own package importable

When the missing module is code you wrote, uv has not installed the package yet. A `src/` directory is not on Python's import path, so a project laid out this way fails:

{{< /filetree/folder >}}
    {{< /filetree/folder >}}
  {{< /filetree/folder >}}
{{< /filetree/container >}}

```console
$ uv run python run.py
Traceback (most recent call last):
  File "/tmp/srcproj/run.py", line 1, in <module>
    from myapp import hello
ModuleNotFoundError: No module named 'myapp'
```

A project without a `[build-system]` table is a bare collection of dependencies, so uv never installs the project's own code. Declare a build backend in [`pyproject.toml`](https://pydevtools.com/handbook/reference/pyproject.toml.md):

```toml {filename="pyproject.toml"}
[build-system]
requires = ["uv_build>=0.12,<0.13"]
build-backend = "uv_build"
```

The next `uv run` builds and installs the project as an [editable install](https://pydevtools.com/handbook/explanation/what-is-an-editable-install.md), and the import resolves:

```console
$ uv run python run.py
   Building myapp @ file:///tmp/srcproj
      Built myapp @ file:///tmp/srcproj
Installed 1 package in 1ms
hi
```

`uv init` writes that table from the start; only `uv init --bare` omits it. [src layout vs flat layout](https://pydevtools.com/handbook/explanation/src-layout-vs-flat-layout.md) covers which layout to choose.

For the related error on relative imports, see [how to fix "attempted relative import with no known parent package"](https://pydevtools.com/handbook/how-to/how-to-fix-importerror-attempted-relative-import-with-no-known-parent-package.md).

## Rename local files that shadow real modules

Python searches the script's own directory before the standard library's, so a file named after a pure-Python standard library module wins. The giveaway is a dotted module name with a trailing clause:

```console
$ python3 send.py
Traceback (most recent call last):
  File "/tmp/shadow/send.py", line 1, in <module>
    from email.mime.text import MIMEText
ModuleNotFoundError: No module named 'email.mime'; 'email' is not a package
```

A local `email.py` shadowed the standard library's `email` package. Because a plain module has no submodules, `email.mime` cannot resolve. Rename the file and the import works:

```console
$ mv email.py mailer.py && python3 send.py
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit

ok
```

Built-in modules such as `sys` and `time` are immune, and so is anything Python already imported at startup, so a local `os.py` does not shadow `os`. When the shadowed name belongs to a third-party package, Python names the culprit in the error itself and suggests the rename by full path.

## Point Jupyter at the project environment

A notebook cell runs in the kernel's environment, not your shell's, so run the same diagnostic inside a cell:

```python
import sys, importlib.util as u
s = u.find_spec("requests")
print(sys.executable)
print(s.origin if s else "NOT FOUND")
```

Install Jupyter as a project dependency so the kernel starts from the project environment:

```bash
uv add --dev jupyter
uv run jupyter lab
```

That kernel reports the project interpreter:

```console
/tmp/demo/.venv/bin/python3
/tmp/demo/.venv/lib/python3.12/site-packages/requests/__init__.py
```

`uv run --with jupyter` builds a temporary overlay environment instead, so the cell reports a cache path such as `/root/.cache/uv/archive-v0/3K6wkXSEhQpmS3f3L_cqN/bin/python`. Project dependencies still import; that unfamiliar path is expected. [How to run a Jupyter notebook with uv](https://pydevtools.com/handbook/how-to/jupyter-notebook-with-uv.md) covers the full setup.

## Inspect the import path

If none of the five cases match, print the search path itself. Python walks these directories in order and takes the first match:

```console
$ uv run python -c "import sys; print(*sys.path, sep='\n')"

/usr/local/lib/python312.zip
/usr/local/lib/python3.12
/usr/local/lib/python3.12/lib-dynload
/tmp/demo/.venv/lib/python3.12/site-packages
```

The empty first entry means the current directory, which is why a local file shadows an installed package. Running `python app.py` puts `app.py`'s own directory there instead. The `site-packages` entry is where installed packages land. If your environment's `site-packages` is missing from that list, the interpreter belongs to no project environment, so relaunch through `uv run` or activate the environment.

## Learn More

- [What is a Python module?](https://pydevtools.com/handbook/explanation/what-is-a-python-module.md) explains how Python resolves module names
- [Why should I use a virtual environment?](https://pydevtools.com/handbook/explanation/why-should-i-use-a-virtual-environment.md) covers the isolation this error keeps exposing
- [How to fix ModuleNotFoundError for numpy during pip install](https://pydevtools.com/handbook/how-to/how-to-fix-modulenotfounderror-no-module-named-numpy-during-pip-install.md) handles the build-time version of this message
- [Python docs: the import system](https://docs.python.org/3/reference/import.html) specifies the search order
- [Python docs: `sys.path`](https://docs.python.org/3/library/sys.html#sys.path) documents how the path is initialized
