CoreMesh

Fix ModuleNotFoundError: No Module Named 'pkg_resources'

Why Python says No module named 'pkg_resources' (or pandas, yaml, cv2), the fixes in order, and a stdlib script that finds the wrong interpreter.

Fix ModuleNotFoundError: No Module Named 'pkg_resources'

ModuleNotFoundError: No module named 'pkg_resources' means the Python interpreter that ran your code looked through every directory on its sys.path and found nothing called pkg_resources. For this specific name the usual cause is simple: pkg_resources ships inside the setuptools distribution, and since Python 3.12 a fresh venv no longer installs setuptools. Run python -m pip install setuptools with the same interpreter that raised the error and the import works again.

The same error with a different name (pandas, requests, yaml, cv2) almost always comes down to one of three things: you installed the package into a different Python than the one running your script, you aren't inside the virtual environment you think you are, or the name you give pip isn't the name you import. The sections below go through those in order, from most common to last resort, with a small script that tells you which case you're in.

What the error actually says#

Here's the full traceback shape you'll see:

text
Traceback (most recent call last):
  File "app.py", line 1, in <module>
    import pkg_resources
ModuleNotFoundError: No module named 'pkg_resources'

A module is just a file (name.py) or a package directory that Python can find on sys.path. When you write import pkg_resources, Python walks the directories on sys.path looking for a matching file or package. If none of them has it, you get this error. Nothing is corrupt. The interpreter that ran app.py simply has no pkg_resources in any directory it searches.

Two details matter for diagnosis. First, only the leftmost name counts. No module named 'sound.effects.echo' with 'sound' missing from sys.path is a sound problem, not an echo problem. Second, the message quotes the import name, which is not always the name you'd type after pip install. More on that below.

Fix 1: install into the interpreter that runs the code#

This is the most common cause by a wide margin. You ran pip install pandas in one Python and executed the script with another. Machines accumulate interpreters: the system one, a python.org install, Homebrew, a venv per project, the one bundled with an editor, the kernel behind a notebook. pip on your PATH belongs to exactly one of them, and it may not be the one running your file.

The fix is to stop typing bare pip and instead ask the interpreter to run pip for you. From the packaging tutorial, the recommended form is:

bash
# Unix/macOS
python3 -m pip install setuptools

# Windows
py -m pip install setuptools

python3 -m pip installs into whatever python3 is. If your script runs under a different executable, use that executable's full path in front of -m pip. In a Jupyter notebook the tutorial recommends {sys.executable} instead of plain python, because the kernel may not be the Python on your shell's PATH:

text
In [1]: import sys
        !{sys.executable} -m pip install setuptools

The script below answers the question directly. It prints which interpreter is running, whether it's inside a virtual environment, which of a list of modules it can find, and the exact install command for that interpreter. Run it with the same command you use to run your failing script, so it reports on the right Python.

python
import importlib.util
import sys

# import name -> name you give pip (only listed when they differ)
PIP_NAME = {
    "pkg_resources": "setuptools",
    "yaml": "PyYAML",
    "cv2": "opencv-python",
    "PIL": "Pillow",
    "sklearn": "scikit-learn",
}

CHECK = ["pkg_resources", "requests", "yaml", "cv2", "PIL", "numpy", "pandas", "json"]

print("interpreter :", sys.executable)
print("version     :", sys.version.split()[0])
in_venv = sys.prefix != sys.base_prefix
print("virtual env :", sys.prefix if in_venv else "none (base interpreter)")
print()

missing = []
for name in CHECK:
    spec = importlib.util.find_spec(name)
    print(f"{name:14} {'ok' if spec else 'MISSING'}")
    if not spec:
        missing.append(PIP_NAME.get(name, name))

print()
if missing:
    print("install into THIS interpreter with:")
    print(f'  "{sys.executable}" -m pip install {" ".join(missing)}')
else:
    print("everything in the list imports from this interpreter")

How to confirm it worked: run the install command the script printed, then run the script again. The module should flip from MISSING to ok. If it doesn't, the install went somewhere else, and that's your real problem.

Fix 2: create and activate a virtual environment#

If the checker says none (base interpreter) but you expected to be in a project environment, the environment either doesn't exist or isn't activated in this shell. Each venv has its own site-packages, isolated from the base Python by default. Packages installed in one don't appear in another.

Create one and activate it:

bash
# Unix/macOS
python3 -m venv .venv
source .venv/bin/activate

# Windows
py -m venv .venv
.venv\Scripts\activate

The source matters on Unix shells. It sets the environment's variables in your current shell rather than in a subprocess that exits immediately. Windows users run the activate script directly, not through source. On Windows PowerShell you may need to allow the script once:

text
PS C:\> Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

Once activated, plain python -m pip install ... installs into the environment without extra flags. If you'd rather not activate, you can still target the environment explicitly with .venv/bin/python -m pip install ... (or .venv\Scripts\python -m pip on Windows).

A few facts from the venv docs worth knowing when debugging: the environment directory contains a pyvenv.cfg file whose home key points at the base Python it was built from, a bin (or Scripts) directory with the interpreter, and lib/pythonX.Y/site-packages (or Lib\site-packages) where packages land. Environments are disposable and not movable. If one looks broken, delete it and recreate it; --clear empties an existing directory before creation.

How to confirm it worked: your prompt usually gains a prefix, and the checker reports the .venv path on the virtual env line.

Fix 3: install setuptools for pkg_resources and distutils#

If the missing name is pkg_resources, the diagnosis is almost always the same. The venv docs record that setuptools is no longer a core venv dependency as of Python 3.12, and the packaging tutorial says the same: versions prior to 3.12 installed setuptools into new environments, and newer ones don't. Code that worked in an older environment breaks in a fresh 3.12+ one, because pkg_resources was never a standard library module. It comes with setuptools.

bash
python3 -m pip install setuptools   # or: py -m pip install setuptools

If the import is in your own code, the better long-term fix is to stop importing pkg_resources and use the standard library's importlib.metadata and importlib.resources instead. That removes the dependency entirely. If the import lives inside a third-party package, you don't control it, so install setuptools and move on.

You'll often see No module named 'distutils' in the same situations: an older package or build script on a new Python. The usual answer is again to install setuptools, which provides a replacement. PEP 632 covers the removal.

How to confirm it worked: python3 -c "import pkg_resources; print('ok')" prints ok with the same interpreter.

The pip name and the import name are not the same thing#

The packaging docs are explicit that "package" means two different things. The thing you pip install is a distribution. The thing you import is a container of modules. Usually they share a name, so people don't notice. When they don't, you get a confusing loop: pip install yaml fails or installs the wrong thing, while import yaml keeps raising the error.

Error says Install with
No module named 'pkg_resources' python -m pip install setuptools
No module named 'yaml' python -m pip install PyYAML
No module named 'cv2' python -m pip install opencv-python
No module named 'PIL' python -m pip install Pillow
No module named 'sklearn' python -m pip install scikit-learn
No module named 'distutils' python -m pip install setuptools
No module named 'pandas' python -m pip install pandas
No module named 'numpy' python -m pip install numpy
No module named 'requests' python -m pip install requests
No module named 'matplotlib' python -m pip install matplotlib
No module named 'openpyxl' python -m pip install openpyxl

Note the capitalization in PIL. Python module names are case-sensitive, and the import is from PIL import Image, not import pil.

Here's a small function that turns an error line into the install command, using the table above. It only looks at the leftmost name, which is the only part that matters for installation.

python
import re

PIP_NAME = {
    "pkg_resources": "setuptools",
    "distutils": "setuptools",
    "yaml": "PyYAML",
    "cv2": "opencv-python",
    "PIL": "Pillow",
    "sklearn": "scikit-learn",
}

def suggest(error_line):
    m = re.search(r"No module named '([^'.]+)", error_line)
    if not m:
        return "not a ModuleNotFoundError line"
    top = m.group(1)
    dist = PIP_NAME.get(top, top)
    note = "" if dist == top else f"   # import name {top!r} ships in {dist!r}"
    return f"python -m pip install {dist}{note}"

for line in [
    "ModuleNotFoundError: No module named 'pkg_resources'",
    "ModuleNotFoundError: No module named 'yaml'",
    "ModuleNotFoundError: No module named 'cv2'",
    "ModuleNotFoundError: No module named 'pandas'",
    "ModuleNotFoundError: No module named 'sound.effects.echo'",
]:
    print(line)
    print("  ->", suggest(line))

If a name isn't in the table and pip install <name> doesn't exist on PyPI, the project's own documentation will name the distribution. Search PyPI for the project, not for the import.

No module named 'settings', 'examples' or 'sample': it's your own code#

When the missing name is something like settings, examples, sample, utils or config, pip can't help. Those are files in your project, and Python can't see them. The rules from the modules tutorial explain every case I've seen:

  • Python searches sys.path, which starts with the directory of the script you ran. If you run python src/app.py and settings.py sits in the project root, the root isn't on sys.path, so import settings fails. Run from the directory that contains the module, or make the project a package and run it with python -m package.app from the parent directory.
  • A directory needs __init__.py to be treated as a package (unless you're deliberately using namespace packages). import examples.demo with no examples/__init__.py is a common tripwire in tutorial repos. An empty file is enough.
  • The tutorial specifically warns that directories with a common name can hide real modules later on the search path. The same applies to files. Name a script yaml.py or requests.py in your working directory and import yaml finds your file instead of the library, then fails on whatever it tries next. Rename the file and delete __pycache__ next to it.
  • Tutorial imports that don't exist in the installed distribution. No module named 'tensorflow.examples' style errors mean the top-level package imports fine but the subpackage the tutorial used isn't shipped in the version you installed. Check the leftmost name with the checker script first. If that one is ok, the problem is the tutorial, not your environment.

Last resorts and the risky ones#

Try these only after the fixes above, and read the warnings.

--user installs. python3 -m pip install --user SomeProject installs into your user site directory, outside any virtual environment. It's a reasonable fallback on a Linux system Python where you can't write to the global site-packages. The flag has no effect inside a virtual environment. The downside is that user-site packages are visible to every script run by that base interpreter, which is exactly the kind of cross-contamination venvs exist to prevent.

Missing pip entirely. If python3 -m pip --version itself fails, bootstrap pip from the standard library with python3 -m ensurepip --default-pip (py -m ensurepip --default-pip on Windows). The packaging tutorial's next step after that is get-pip.py, with a clear warning: it does not coordinate with an operating system package manager and can leave a system Python in an inconsistent state. If your Python came from apt, dnf or similar, prefer the distribution's own pip package.

sudo pip install. Don't. The packaging tutorial says not to run any of its commands with sudo. A permissions error means you're writing into a system-owned Python. Create a virtual environment instead and the error goes away.

--system-site-packages. python -m venv --system-site-packages .venv gives the environment access to the base Python's packages. It will make a missing import "work" if the base has the package, but it also means the environment no longer tells you what your project actually depends on. I'd only use it for packages that are painful to build and already provided by the OS.

Common mistakes#

  • Fixing it in the terminal, then running from an editor or notebook. The editor's configured interpreter or the notebook kernel is a separate Python. Point the editor at .venv/bin/python, or install with {sys.executable} from inside the notebook.
  • Activating the venv in one shell tab and running the script in another. Activation only affects the shell you ran it in. Check the checker's virtual env line in the same tab you run from.
  • Installing with pip while running with python3. On many systems these belong to different interpreters. Always python3 -m pip or py -m pip.
  • Typing the import name into pip. pip install yaml, pip install cv2, pip install PIL and pip install sklearn are all wrong. See the table.
  • Assuming pkg_resources is part of Python. It never was. It comes with setuptools, which 3.12+ environments don't include by default.
  • A file in your project shadowing the library. test.py, email.py, random.py, yaml.py and friends. If the traceback points inside your own file when you only imported a library, that's the shadow.
  • Copying a venv to another machine or path. The venv docs say environments aren't movable. pyvenv.cfg still points at the old home. Recreate it.
  • Running python app.py from the wrong directory. The script's directory is on sys.path; your current directory is not unless it's the same place.

Quick checklist#

  1. Read the exact name in quotes. Only the leftmost part matters.
  2. Run the checker script with the same command you use for the failing script. Note interpreter and virtual env.
  3. Install with that interpreter: python3 -m pip install <dist> or "<path shown>" -m pip install <dist>. Never bare pip, never sudo.
  4. For pkg_resources or distutils, the distribution is setuptools.
  5. For yaml, cv2, PIL, sklearn, use PyYAML, opencv-python, Pillow, scikit-learn.
  6. No venv? python3 -m venv .venv then source .venv/bin/activate (or .venv\Scripts\activate).
  7. Missing name is your own file? Check __init__.py, the directory you ran from, and whether a local file shadows a library.
  8. Re-run the checker. The module should read ok. If not, the install went to a different Python. Go back to step 2.

Quick answers

Why do I get No module named 'pkg_resources' on Python 3.12 when it worked before?

Starting with Python 3.12, venv no longer installs setuptools into new environments, and pkg_resources is part of setuptools. Install it with python -m pip install setuptools using the same interpreter that raised the error.

I ran pip install pandas but still get No module named 'pandas'. Why?

The pip on your PATH belongs to a different Python than the one running your script. Install with python3 -m pip install pandas (or py -m pip on Windows), or use the full path of the interpreter your script runs under.

Why does pip install yaml or pip install cv2 not fix the error?

The name you import and the name you install can differ. yaml comes from PyYAML, cv2 from opencv-python, PIL from Pillow, and sklearn from scikit-learn.

What about No module named 'distutils'?

It appears in the same situations as pkg_resources, usually older build scripts on a newer Python. Installing setuptools into the same interpreter is the usual fix.

The missing module is 'settings' or 'examples', which isn't on PyPI. What now?

That's a file in your own project. Make sure you run from the directory that contains it, that package directories have an __init__.py, and that no local file shares a name with a library you import.

Did this solve it?

One tap. No account.

Saved you an hour? Send a tip.

USDC or ETH on Base, Ethereum, Arbitrum and more. Keeps the notes free and the examples running.

Base

Network

0xc783bc5c3fa14cEC3f09A22284bC91C5AF0d59e1
Open in wallet · 5 USDC

On a computer? Scan the code with your phone wallet, or copy the address.

Pick the network your wallet or exchange uses. USDC works on all six; ETH on Base, Ethereum, Arbitrum and Optimism. Don't send on Tron or Solana: this address doesn't exist there. Tips are optional and unlock nothing; every guide stays free.

Discussion

Start the discussion

`code` and ``` blocks work

No account needed. Comments are read before they show up, usually the same day. Your email is never asked for.

Indra Wijaya

Builds and runs AI agents, bots and content pipelines, and writes down what works and what broke.

About · Email · RSS

Keep reading

New notes, no spam.

One post at a time, only when there's something worth reading. Follow in any feed reader.

Subscribe via RSS