Skip to Content
Python Intermediate: Write Code You Won't Be Embarrassed to Share
Intermediate
0 likes
Courses
Python Intermediate: Write Code You Won't Be Embarrassed to Share

Pinning Python Dependencies With requirements.txt

How to record the exact package versions a project needs and rebuild the same environment on another machine. After this, "it works on my computer" stops being the answer.

Course content

Sign in to save your progress.

Course Home

A virtual environment is disposable. The list of what goes into it is not. requirements.txt is that list: a plain text file with the packages, and ideally the exact versions, your project needs. With it, anyone can rebuild your environment with one command.

Skip ahead: If you already pin versions, rebuild environments from requirements.txt, and know the difference between pinning an app and a library, take the section quiz.

Why this matters

"It works on my computer" usually means "my computer has different package versions than yours". You installed a library eight months ago. Your coworker installs it today and gets a newer version that changed a function. Same code, different result. Nobody did anything wrong. The project just never wrote down what it depends on.

Create the file with pip freeze

Inside an activated environment, pip freeze prints every installed package with its exact version:

python3 -m venv .venv
source .venv/bin/activate
python -m pip install --quiet requests
python -m pip freeze > requirements.txt
cat requirements.txt
certifi==...
charset-normalizer==...
idna==...
requests==2...
urllib3==...

You installed one package and got five lines. The other four are dependencies of requests. That is normal. Freezing them too means the whole set is reproducible, not just the part you remember installing.

⚠ Warning: Only run pip freeze inside the project's activated environment. Run it against your global Python and you get every package you ever installed for every project, and the file becomes useless.

Rebuild the environment from the file

On a new computer, or after deleting a broken .venv:

python3 -m venv .venv
source .venv/bin/activate          # Windows: .venv\Scripts\activate
python -m pip install -r requirements.txt

To prove it gives the same result, build a second environment from the same file and compare it with the original list:

python3 -m venv new-env
new-env/bin/python -m pip install --quiet -r requirements.txt
new-env/bin/python -m pip freeze | diff - requirements.txt && echo "Same versions"
Same versions

Two environments, built at different times, with identical versions. That is what you want for anything that has to behave the same everywhere.

Pinned or loose versions?

There are three common ways to write a line, and they are not equally safe.

  • requests==2.32.3 (pinned). Exactly this version. Best for applications and scripts you deploy: the same code gets the same packages every time. The downside is that you don't get bug fixes until you update the pin yourself.
  • requests>=2.31,<3 (a range). Any version in that range. Better for libraries that other projects install, because strict pins in a library cause conflicts with the projects using it.
  • requests (nothing). Whatever is newest on the day someone installs. Fine for a quick experiment. For anything else, you are betting that no future release changes anything you use.

For most people taking this course, the answer is simple: you are writing applications and scripts, so pin. The range style matters later, when you publish a package, which is covered in the Python Advanced course.

Updating on purpose

Pinning doesn't mean never updating. It means updating when you decide to, not when a release happens to come out. A safe routine:

  1. Check what is outdated with python -m pip list --outdated.
  2. Upgrade one package, for example python -m pip install --upgrade requests.
  3. Run your tests or at least run the script.
  4. If it works, freeze again and commit the new requirements.txt. If it doesn't, you know exactly which upgrade broke it.

A real-world example

A small team has a script that pulls orders from an API every morning. A new hire sets it up on a fresh laptop. Without a requirements file, they install whatever is newest, and one of the libraries changed how it handles dates. The script runs without errors and quietly writes the wrong dates. With a pinned requirements.txt in the repository, the new laptop gets the same versions as the server, and the problem never happens.

Common mistakes

  • Freezing the global Python. Covered above. Check that the environment is active first.
  • Editing requirements.txt by hand and forgetting dependencies. If you add a line by hand, install from the file and freeze again so the dependencies get pinned too.
  • Not committing it. The file is useless if it only lives on your computer. It belongs in Git, next to your code. .venv doesn't.
  • Installing extra tools into the project environment. Things you use only for yourself, like a different code formatter, end up in the freeze. Some projects keep them in a separate requirements-dev.txt.

💡 Tip: Test your file the honest way once in a while: delete .venv, create a new one, install from requirements.txt, and run the project. If it fails, the file is incomplete, and it is better you find out than the next person.

What happens if you skip this step

The project works for as long as it lives on one computer with one environment. The day it has to run anywhere else, a server, a coworker's laptop, your own new laptop, someone has to guess the versions. Guessing usually works. When it doesn't, the bug looks like a bug in your code, and you spend hours in the wrong place.

If your laptop died today, would your project still run on the next one exactly the same way?

About

How to record the exact package versions a project needs and rebuild the same environment on another machine. After this, "it works on my computer" stops being the answer.

Duration
5 min
Last update
09/19/2026
Was this helpful?
​ 0 ​ 0

Comments (0)

Sign in to comment

No comments yet.