Python
Python Modules
Version Checking
Programming
Software Development

How do I check the versions of Python modules?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

The fastest way to check a Python module's version is python -m pip show package_name, which prints the version along with other metadata. From within a script, use importlib.metadata.version("package_name") (Python 3.8+). Several other methods exist depending on whether you need to check one package, all packages, or verify versions programmatically at runtime.

Method 1: pip show (Single Package)

This is the most reliable method for checking a specific package:

bash
python -m pip show requests

Output:

 
1Name: requests
2Version: 2.31.0
3Summary: Python HTTP for Humans.
4Home-page: https://requests.readthedocs.io
5Author: Kenneth Reitz
6License: Apache 2.0
7Location: /home/user/.venv/lib/python3.11/site-packages
8Requires: charset-normalizer, idna, urllib3, certifi

The Location field also tells you where the package is installed, which is useful for debugging interpreter mismatches.

Method 2: pip list (All Packages)

To see every installed package and its version:

bash
python -m pip list

Output:

 
1Package            Version
2------------------ ---------
3certifi            2023.7.22
4charset-normalizer 3.3.0
5idna               3.4
6pip                23.3.1
7requests           2.31.0
8urllib3             2.0.7

For machine-readable output, use the --format flag:

bash
1# JSON output for scripting
2python -m pip list --format=json
3
4# Show only outdated packages
5python -m pip list --outdated

Method 3: importlib.metadata (Programmatic, Python 3.8+)

This is the modern, recommended way to check versions from within Python code:

python
1from importlib.metadata import version, PackageNotFoundError
2
3try:
4    v = version("requests")
5    print(f"requests version: {v}")
6except PackageNotFoundError:
7    print("requests is not installed")

This works for any installed package, regardless of whether the package exposes a __version__ attribute.

Method 4: __version__ Attribute

Many packages define a __version__ attribute on their top-level module:

python
1import requests
2print(requests.__version__)  # 2.31.0
3
4import flask
5print(flask.__version__)     # 3.0.0
6
7import numpy
8print(numpy.__version__)     # 1.26.0

This is simple but has a significant limitation: not all packages follow this convention. Some use different attribute names, and some do not expose a version at runtime at all.

python
1# These will raise AttributeError
2import PIL
3print(PIL.__version__)  # AttributeError (use PIL.__version__ from Pillow, or importlib)
4
5import google.cloud.storage
6print(google.cloud.storage.__version__)  # may or may not exist

Method 5: pkg_resources (Legacy)

The pkg_resources module from setuptools was the standard before importlib.metadata:

python
1import pkg_resources
2
3version = pkg_resources.get_distribution("requests").version
4print(version)  # 2.31.0

This still works but is considered legacy. importlib.metadata is faster (it does not scan all packages on import) and is part of the standard library. Prefer importlib.metadata for new code.

Method 6: CLI Tools from Packages

Some packages provide their own command-line version flag:

bash
1python --version               # Python itself
2django-admin --version         # Django
3flask --version                # Flask
4pytest --version               # pytest
5black --version                # Black formatter
6celery --version               # Celery

This is convenient but inconsistent. Not every package provides a CLI, and the flag name varies (--version, -V, version subcommand).

Comparison of Methods

MethodScopeWorks Without ImportPython VersionReliability
pip showSingle packageYes (CLI)AnyHigh
pip listAll packagesYes (CLI)AnyHigh
importlib.metadataSingle packageN/A (code)3.8+High
__version__Single packageNo (must import)AnyMedium (not universal)
pkg_resourcesSingle packageN/A (code)AnyHigh (but slow)
CLI --versionSingle packageYes (CLI)AnyMedium (not universal)

Checking Python's Own Version

To check the Python interpreter version (not a third-party module):

bash
# From the command line
python --version
python3 --version
python
1# From within Python
2import sys
3print(sys.version)           # '3.11.5 (main, Sep 11 2023, 08:19:27)'
4print(sys.version_info)      # sys.version_info(major=3, minor=11, micro=5, ...)
5print(sys.version_info[:2])  # (3, 11) - just major.minor

For runtime version checks in code (e.g., requiring Python 3.9+):

python
1import sys
2
3if sys.version_info < (3, 9):
4    raise RuntimeError("Python 3.9 or higher is required")

Programmatic Version Comparison

When you need to check versions at runtime (e.g., to use a feature that was added in a specific version), use packaging.version:

python
1from importlib.metadata import version
2from packaging.version import Version
3
4installed = Version(version("requests"))
5
6if installed >= Version("2.28.0"):
7    # Use the newer API
8    pass
9else:
10    # Fall back to the older API
11    pass

Do not compare version strings directly. String comparison gives wrong results: "2.9.0" > "2.10.0" evaluates to True because "9" > "1" lexicographically.

Freezing and Requirements Files

To capture all installed package versions for reproducibility:

bash
1# Generate a requirements file
2python -m pip freeze > requirements.txt
3
4# Install from a requirements file
5python -m pip install -r requirements.txt

The output of pip freeze is a pinned version list:

 
1certifi==2023.7.22
2charset-normalizer==3.3.0
3requests==2.31.0
4urllib3==2.0.7

For more robust dependency management, consider pip-tools, poetry, or pdm which handle transitive dependencies and lock files.

Common Pitfalls

  • Using a bare pip command that belongs to a different Python interpreter. Always use python -m pip to ensure you are checking the correct environment.
  • Comparing version strings with < or > operators. "2.9" > "2.10" is True in Python because it is a lexicographic comparison. Use packaging.version.Version for correct semantic comparison.
  • Relying on __version__ for packages that do not define it. Use importlib.metadata.version() instead, which reads the installed package metadata regardless of what the module exposes.
  • Checking versions in a terminal but running code in a different environment (system Python vs. venv vs. conda). The version you see may not be the version your code imports.
  • Using pkg_resources in performance-sensitive code. It scans all installed packages on first import, which adds noticeable startup time. importlib.metadata is significantly faster.

Summary

  • For a quick check, use python -m pip show package_name to see the version of a specific package or python -m pip list for all packages.
  • In code, use importlib.metadata.version("package_name") (Python 3.8+). It is reliable, fast, and works for every installed package.
  • The __version__ attribute works for many popular packages but is not universal. Do not depend on it for arbitrary packages.
  • Always use python -m pip instead of bare pip to avoid interpreter mismatches.
  • Use packaging.version.Version for programmatic version comparison. Never compare version strings lexicographically.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.