Tools

How to Check the Version of a Python Package With pip

Tools · Published 2026-10-24

An old leather luggage tag with a handwritten date, May 15-96
An old leather luggage tag with a handwritten date.

Run python -m pip show <package> and read the Version: line, or use python -m pip list to see every installed package. From Python code, call importlib.metadata.version("package") (Python 3.8+). Always run these with the same interpreter or virtual environment your program uses, because each environment has its own packages.

pip show: one package in detail

python -m pip show requests
Name: requests
Version: 2.32.3
Summary: Python HTTP for Humans.
Home-page: https://requests.readthedocs.io
Author: Kenneth Reitz
Author-email: me@kennethreitz.org
License: Apache-2.0
Location: /home/dev/project/.venv/lib/python3.13/site-packages
Requires: certifi, charset-normalizer, idna, urllib3
Required-by: 

Besides the version, the output tells you where the package is installed (Location), which is the fastest way to discover that you are looking at the wrong environment. Requires and Required-by show its dependencies and dependents. You can pass several names at once (pip show requests urllib3), and pip show -f also lists the installed files. See the pip show reference.

If the package is not installed, pip prints a warning and exits with status 1, which is handy in shell scripts:

python -m pip show nosuchpkg; echo "exit=$?"
WARNING: Package(s) not found: nosuchpkg
exit=1

pip list and pip freeze: all packages

pip list prints a table of every distribution in the environment:

python -m pip list
Package            Version
------------------ ----------
certifi            2026.10.23
charset-normalizer 3.5.2
idna               3.20
packaging          26.3
pip                26.2.2
requests           2.32.3
urllib3            2.8.0

To find one package, filter the output. pip freeze prints name==version lines in requirements-file format, which are easy to grep:

python -m pip freeze | grep -i requests          # Linux / macOS
python -m pip freeze | findstr /i requests       # Windows cmd
python -m pip list | Select-String requests      # PowerShell
requests==2.32.3

Use -i because names are case-insensitive (PyYAML, Django). Differences worth knowing:

CommandOutputNotes
pip show NAMEMetadata for one or more packagesIncludes location and dependencies
pip listTable of all packages--outdated, --format=json, --not-required
pip freezename==version linesHides pip/setuptools by default; packages installed from VCS or local paths appear as URLs
pip inspectFull JSON report of the environmentpip 22.2+; meant for tooling

For scripts, pip list --format=json is more robust than parsing the table:

[{"name": "certifi", "version": "2026.10.23"}, {"name": "charset-normalizer", "version": "3.5.2"}, ...]

Why python -m pip instead of pip

The bare pip command is whichever pip script comes first on your PATH, and it may belong to a different Python than the one that runs your code. On the same machine, the system interpreter and a project virtual environment can report completely different results:

python3 -m pip show requests | head -2          # system Python
.venv/bin/python -m pip show requests | head -2  # project venv
.venv/bin/python -m pip show pandas
Name: requests
Version: 2.34.2
Name: requests
Version: 2.32.3
WARNING: Package(s) not found: pandas

python -m pip guarantees that pip operates on the interpreter you named, which is what the Python Packaging User Guide recommends. On Windows, py -m pip does the same through the launcher (py -3.12 -m pip list targets a specific version). To check which interpreter you are actually running:

python -c "import sys; print(sys.executable)"

Virtual environments and conda

Checking the version from Python code

importlib.metadata, in the standard library since Python 3.8, reads the same installed metadata that pip uses, without starting a subprocess or importing the package:

from importlib.metadata import version, PackageNotFoundError

print(version("requests"))

try:
    version("nosuchpkg")
except PackageNotFoundError as exc:
    print("not installed:", exc)
2.32.3
not installed: No package metadata was found for nosuchpkg

On Python 3.7 and older, install the importlib-metadata backport and import from importlib_metadata. Avoid the old pkg_resources.get_distribution() API: it is slow, deprecated, and part of setuptools rather than the standard library.

version() takes the distribution name (what you pip install), not the import name. Most of the time they match, but not always:

version("PyYAML")      # '6.0.3'
version("yaml")        # PackageNotFoundError: No package metadata was found for yaml

Other common mismatches: scikit-learn / sklearn, Pillow / PIL, beautifulsoup4 / bs4, opencv-python / cv2. Names are normalised, so charset-normalizer and charset_normalizer both work. If you only know the import name, importlib.metadata.packages_distributions() (Python 3.10+) maps it back: packages_distributions()["charset_normalizer"] returns ['charset-normalizer'].

To list everything from code, iterate over distributions():

from importlib.metadata import distributions

for dist in sorted(distributions(), key=lambda d: d.metadata["Name"].lower()):
    print(f'{dist.metadata["Name"]}=={dist.version}')

The __version__ attribute and its caveats

Many packages expose a version string on the module:

import requests
print(requests.__version__)
2.32.3

It is a convention, not a standard, so it is unreliable as a general method:

Prefer importlib.metadata.version() and keep __version__ for quick interactive checks.

Which versions are available?

To see what you could install, ask the index. pip index versions (pip 21.2+) lists available releases and shows what is installed:

python -m pip index versions requests
requests (2.34.2)
Available versions: 2.34.2, 2.34.1, 2.34.0, 2.33.1, 2.33.0, 2.32.5, 2.32.4, 2.32.3, ...
  INSTALLED: 2.32.3
  LATEST:    2.34.2

The command is marked experimental, and older pip releases print WARNING: pip index is currently an experimental command. It may be removed/changed in a future release without prior warning., so do not build scripts that depend on its exact output. Pre-releases are excluded unless you add --pre. Two alternatives:

python -m pip list --outdated          # installed packages with a newer release
python -m pip install requests==0      # trick: the error lists all versions
Package  Version Latest Type
-------- ------- ------ -----
requests 2.32.3  2.34.2 wheel

ERROR: Could not find a version that satisfies the requirement requests==0 (from versions: 0.2.0, 0.2.1, ..., 2.34.1, 2.34.2)

The older form pip install requests== (empty version) no longer works in current pip; it fails with ERROR: Invalid requirement. Asking for an impossible version such as ==0 still produces the list.

The project page on PyPI (https://pypi.org/project/requests/#history) shows the same release history with dates.

Comparing versions correctly with packaging

Never compare version strings as strings: "2.10.0" > "2.9.0" is False because the comparison is character by character. The packaging library implements the official version specifier rules (PEP 440), including pre-releases and post-releases:

from importlib.metadata import version
from packaging.version import Version
from packaging.specifiers import SpecifierSet

installed = Version(version("requests"))
print(installed >= Version("2.32"))
print("2.10.0" > "2.9.0", Version("2.10.0") > Version("2.9.0"))
print(Version("1.0rc1") < Version("1.0"), Version("1.0.post1") > Version("1.0"))
print(installed.major, installed.minor, installed.micro)
print(version("requests") in SpecifierSet(">=2.31,<3"))
True
False True
True True
2 32 3
True

A typical use is a guard at program start-up:

import sys
from importlib.metadata import version
from packaging.version import Version

if Version(version("requests")) < Version("2.32"):
    sys.exit(f"requests>=2.32 required, found {version('requests')}")

packaging is a third-party package (pip install packaging), though it is present in most environments because pip and many build tools depend on it. Version() rejects strings that are not valid PEP 440 versions with packaging.version.InvalidVersion: Invalid version: 'latest'. For real dependency constraints, declare them in pyproject.toml or a requirements file instead of checking at runtime.

Troubleshooting

Summary

From the shell, use python -m pip show NAME for one package, python -m pip list or pip freeze | grep for an overview, and pip list --outdated or pip index versions NAME for newer releases. From code, use importlib.metadata.version() with the distribution name, treat __version__ as a convenience only, and compare versions with packaging.version.Version, never as strings. In every case, make sure you are querying the same environment that runs your code.

Read next

More in Tools