pip freeze is your time machine for Python environments, letting you perfectly recreate a specific setup later.
Here’s a quick look at pip freeze in action. Imagine you’ve got a project that needs requests version 2.28.1 and numpy version 1.23.0.
$ pip install requests==2.28.1 numpy==1.23.0
Collecting requests==2.28.1
Downloading requests-2.28.1-py3-none-any.whl (62 kB)
...
Collecting numpy==1.23.0
Downloading numpy-1.23.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (17.1 MB)
...
Successfully installed numpy-1.23.0 requests-2.28.1
Now, to capture these exact versions, you run:
$ pip freeze
numpy==1.23.0
requests==2.28.1
This output is a snapshot. You can save this to a file, say requirements.txt:
$ pip freeze > requirements.txt
Later, on a new machine or in a fresh virtual environment, you can install precisely these packages by pointing pip to your requirements.txt file:
$ pip install -r requirements.txt
This ensures that your project will behave identically, regardless of when or where you install its dependencies.
The core problem pip freeze solves is dependency hell, the nightmare of incompatible package versions. By explicitly listing every installed package and its exact version, you create a reproducible environment. This is crucial for collaboration, continuous integration (CI) pipelines, and deploying applications to production. Without it, a package might update to a new, breaking version on one machine, while another machine still runs the old version, leading to "it works on my machine" syndrome.
Internally, pip freeze queries the site-packages directory of your current Python environment. It iterates through all installed packages, reads their metadata (usually found in .dist-info or .egg-info directories within site-packages), and formats this information into the package==version string. It’s a direct lookup of what’s currently installed and active.
The most surprising thing about pip freeze is that it doesn’t actually know about your project’s intended dependencies; it only reports what is currently installed. This distinction is vital. If you manually installed requests v2.28.1 and then also installed a package that requires requests v2.27.0, pip freeze will show requests==2.28.1. If you then use pip freeze > requirements.txt and try to reinstall on a clean environment, you’ll install requests==2.28.1, which might break the package that actually needed v2.27.0. This is why tools like Poetry or Pipenv, which manage dependencies more holistically and can resolve conflicts, are often preferred for managing complex projects.
You control the output of pip freeze by controlling what’s installed in your Python environment. If you’re in a virtual environment, it only shows packages installed within that environment, preventing pollution of your global Python installation. This isolation is a key benefit of using virtual environments.
The next hurdle you’ll face is understanding how to manage transitive dependencies and potential version conflicts when using requirements.txt files generated by pip freeze.