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.

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:
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:
# 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:
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.
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:
# 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:
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.
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.
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 runpython src/app.pyandsettings.pysits in the project root, the root isn't onsys.path, soimport settingsfails. Run from the directory that contains the module, or make the project a package and run it withpython -m package.appfrom the parent directory. - A directory needs
__init__.pyto be treated as a package (unless you're deliberately using namespace packages).import examples.demowith noexamples/__init__.pyis 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.pyorrequests.pyin your working directory andimport yamlfinds 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 isok, 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 envline in the same tab you run from. - Installing with
pipwhile running withpython3. On many systems these belong to different interpreters. Alwayspython3 -m piporpy -m pip. - Typing the import name into pip.
pip install yaml,pip install cv2,pip install PILandpip install sklearnare all wrong. See the table. - Assuming
pkg_resourcesis 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.pyand 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.cfgstill points at the oldhome. Recreate it. - Running
python app.pyfrom the wrong directory. The script's directory is onsys.path; your current directory is not unless it's the same place.
Quick checklist#
- Read the exact name in quotes. Only the leftmost part matters.
- Run the checker script with the same command you use for the failing script. Note
interpreterandvirtual env. - Install with that interpreter:
python3 -m pip install <dist>or"<path shown>" -m pip install <dist>. Never barepip, neversudo. - For
pkg_resourcesordistutils, the distribution issetuptools. - For
yaml,cv2,PIL,sklearn, usePyYAML,opencv-python,Pillow,scikit-learn. - No venv?
python3 -m venv .venvthensource .venv/bin/activate(or.venv\Scripts\activate). - Missing name is your own file? Check
__init__.py, the directory you ran from, and whether a local file shadows a library. - 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.
Sorry about that. What was missing?
from 0 readers
Saved you an hour? Send a tip.
USDC or ETH on Base, Ethereum, Arbitrum and more. Keeps the notes free and the examples running.
Network
0xc783bc5c3fa14cEC3f09A22284bC91C5AF0d59e1
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
Next note