KAHIBARO
Discord Login Register

5.4. pip and Package Management

Why Package Management Matters

Modern backend development depends on thousands of reusable libraries. Instead of writing everything from scratch, you install and reuse these libraries in your projects.

Python uses a tool called pip to:

A package manager solves three main problems:

  1. Discovering packages by name.
  2. Installing correct versions with all their dependencies.
  3. Reproducing the same setup on another machine.

Without proper package management, your code might:

In this chapter, you will learn how to use pip in a way that is safe and suitable for backend projects.


Installing and Upgrading Packages with pip

When you installed Python, you normally got pip along with it.

You can check that pip is available with:

bash
pip --version

or, more explicit:

bash
python -m pip --version

Using python -m pip is often safer, because it guarantees you use the pip that belongs to that specific Python interpreter.

Basic installation

To install a package:

bash
pip install requests

This will:

You can then use it in your code:

python
import requests
response = requests.get("https://example.com")
print(response.status_code)

Installing a specific version

You often want fixed versions in backend projects, so your environment is predictable.

bash
pip install "requests==2.31.0"

Other version operators:

OperatorMeaningExample
==Exactly this versionrequests==2.31.0
>=This version or newerrequests>=2.28.0
<=This version or olderrequests<=2.31.0
>Strictly higher versionrequests>2.0.0
<Strictly lower versionrequests<3.0.0
~=Compatible release, same major.minor seriesrequests~=2.31

Example:

bash
pip install "fastapi~=0.111"

This means “install FastAPI 0.111.x, but not 0.112 or higher”.

In backend projects, always pin versions in your dependency files, for example package==1.2.3. This makes deployments and production behavior predictable.

Upgrading and reinstalling

Upgrade a package to the latest version:

bash
pip install --upgrade requests
# or shorter:
pip install -U requests

Upgrade to a specific version:

bash
pip install "requests==2.32.0"

Force reinstall (useful if an installation got corrupted):

bash
pip install --force-reinstall "requests==2.31.0"

Uninstalling packages

To remove a package:

bash
pip uninstall requests

You will be asked to confirm. Answer y or yes to proceed.


Listing and Inspecting Installed Packages

Understanding what is installed in your environment is important, especially on servers or in virtual environments.

Listing installed packages

To list all installed packages:

bash
pip list

Example output (shortened):

text
Package    Version
---------- -------
pip        24.0
setuptools 69.0.0
requests   2.31.0
fastapi    0.111.0
uvicorn    0.30.0

To include packages that pip did not install (like some system packages):

bash
pip list --local

Showing details about a package

To see detailed information about a specific package:

bash
pip show requests

Example output:

text
Name: requests
Version: 2.31.0
Summary: Python HTTP for Humans.
Home-page: https://requests.readthedocs.io
Author: Kenneth Reitz
License: Apache 2.0
Location: /path/to/venv/lib/python3.11/site-packages
Requires: certifi, charset-normalizer, idna, urllib3
Required-by: some-other-package

This helps you:

Checking outdated packages

To see which installed packages have newer versions available:

bash
pip list --outdated

Example:

text
Package  Version Latest Type
-------- ------- ------ -----
uvicorn  0.30.0  0.31.0 wheel
fastapi  0.111.0 0.112.0 wheel

In production projects, you normally do not upgrade everything blindly. You upgrade carefully and test.


Requirements Files and Dependency Freezing

For real backend projects, you must be able to recreate the exact same environment on:

You do this using a requirements file.

What is a requirements file?

A requirements.txt file is a plain text file that lists all your project dependencies.

Simple example:

text
fastapi==0.111.0
uvicorn[standard]==0.30.0
sqlalchemy==2.0.30
psycopg2-binary==2.9.9
python-dotenv==1.0.1

Installing from a requirements file

To install everything from this file:

bash
pip install -r requirements.txt

This is how you:

Creating a requirements file manually

For small projects, you can just write requirements.txt by hand.

Example scenario:

You create a new FastAPI project and install some packages:

bash
pip install fastapi uvicorn[standard]
pip install sqlalchemy psycopg2-binary

Then you create requirements.txt:

text
fastapi==0.111.0
uvicorn[standard]==0.30.0
sqlalchemy==2.0.30
psycopg2-binary==2.9.9

You get the exact installed versions with:

bash
pip show fastapi uvicorn sqlalchemy psycopg2-binary

or by using pip freeze as explained next.

Freezing dependencies with pip freeze

pip freeze prints all installed packages in a format that pip install -r understands:

bash
pip freeze

Example output (shortened):

text
anyio==4.4.0
fastapi==0.111.0
idna==3.7
pydantic==2.8.0
sniffio==1.3.1
starlette==0.37.2
typing_extensions==4.12.2
uvicorn==0.30.0

You can redirect this into a file:

bash
pip freeze > requirements.txt

Now requirements.txt contains the full dependency tree, not just your top level packages, for example:

text
fastapi==0.111.0
pydantic==2.8.0
starlette==0.37.2
typing_extensions==4.12.2
uvicorn==0.30.0
...

pip freeze includes everything in your current environment. Only run it inside a clean virtual environment that belongs to a single project. Never run it in a global interpreter.

Top level vs full freeze

There are two common strategies:

StrategyDescriptionProsCons
Top level onlyYou list only the libraries you directly useShort and readable fileLess precise, installs latest sub-deps
Full freeze (pip freeze)You list every installed dependencyFully reproducible environmentsLong file, includes indirect dependencies

For backend projects you want reproducibility, so full freeze is common, especially for production.

A typical approach:

  1. Maintain requirements.in with only top level dependencies:
text
   fastapi
   uvicorn[standard]
   sqlalchemy
   psycopg2-binary
  1. Generate requirements.txt using a tool (such as pip-tools) that pins all versions.

You will learn about more advanced tools later. For now it is enough to understand the idea.


Optional Dependencies and Extras

Some packages provide optional features that you can enable with extras. You saw a glimpse of this with uvicorn[standard].

What are extras?

An extra is a named group of additional dependencies that add some feature, usually written in square brackets.

Example:

bash
pip install "uvicorn[standard]"

uvicorn defines an extra called standard. It might include things like:

You get a more fully featured Uvicorn server with one command.

You can also combine extras:

bash
pip install "somepackage[redis,postgres]"

This installs:

You do not need to know how to define extras yet, just how to use them when a package documents them.

Optional dependencies in practice

Examples you will likely see in backend work:

bash
pip install "sqlalchemy[asyncio]"
pip install "fastapi[all]"
pip install "httpx[http2]"

You should always follow the project documentation. It will mention which extras you should enable for your use case.


Managing Dependencies Across Environments

Backend applications typically have multiple environments:

You usually want:

Splitting dependencies: prod vs dev

You can use multiple requirements files.

Example:

requirements.txt (for production):

text
fastapi==0.111.0
uvicorn[standard]==0.30.0
sqlalchemy==2.0.30
psycopg2-binary==2.9.9
python-dotenv==1.0.1

requirements-dev.txt (for development):

text
-r requirements.txt
pytest==8.2.0
pytest-asyncio==0.23.0
pytest-cov==5.0.0
black==24.4.2
isort==5.13.2

The -r requirements.txt line tells pip: “first install everything from requirements.txt”.

To install only production dependencies:

bash
pip install -r requirements.txt

To install both production and dev dependencies:

bash
pip install -r requirements-dev.txt

Example: different environments

Imagine your FastAPI project:

So your workflow:

  1. On your development machine:
bash
   pip install -r requirements-dev.txt
  1. On the production server:
bash
   pip install -r requirements.txt

This keeps production environments smaller and reduces attack surface.


Common pip Commands for Backend Projects

Here is a summary of pip commands you will use again and again.

Installation commands

TaskCommand example
Install latest versionpip install fastapi
Install specific versionpip install "fastapi==0.111.0"
Install with extraspip install "uvicorn[standard]"
Install from requirementspip install -r requirements.txt
Install from local directorypip install . (in a directory with pyproject.toml)

Inspection commands

TaskCommand example
Check pip versionpip --version
List installed packagespip list
List outdated packagespip list --outdated
Show details for a packagepip show fastapi
Generate a full freeze filepip freeze > requirements.txt

Maintenance commands


TaskCommand example
Upgrade a packagepip install --upgrade fastapi
Upgrade to specific verpip install "fastapi==0.112.0"
Uninstall a packagepip uninstall fastapi
Reinstall a packagepip install --force-reinstall package

Typical Workflow in a Backend Project

To put all of this together, here is a simple but realistic example workflow.

Starting a new backend project

  1. Create and activate a virtual environment (covered in the “Virtual Environments” chapter).
  2. Install initial dependencies:
bash
   pip install fastapi uvicorn[standard]
  1. Start coding:
python
   # main.py
   from fastapi import FastAPI
   app = FastAPI()
   @app.get("/")
   def read_root():
       return {"message": "Hello Backend"}
  1. Run the app:
bash
   uvicorn main:app --reload
  1. Freeze dependencies:
bash
   pip freeze > requirements.txt

Now you have a reproducible environment.

Adding a new library later

You decide to store data in PostgreSQL using SQLAlchemy:

  1. Install new dependencies:
bash
   pip install sqlalchemy psycopg2-binary
  1. Update requirements.txt:
bash
   pip freeze > requirements.txt
  1. Commit code and requirements.txt to version control.

Setting up on another machine

On another computer or a server:

  1. Create and activate a virtual environment.
  2. Install dependencies:
bash
   pip install -r requirements.txt

Now this environment has exactly the same package versions, so your backend behaves the same.


Good Practices and Common Pitfalls

You now know the mechanics of pip. To use it safely in backend work, keep these rules in mind.

Good practices

Example README section:

text
## Setup
1. Create virtual environment:
   python -m venv .venv
2. Activate it:
   # Windows:
   .venv\Scripts\activate
   # macOS / Linux:
   source .venv/bin/activate
3. Install dependencies:
   pip install -r requirements.txt

Common pitfalls

PitfallWhy it is a problemBetter approach
Using global Python for all projectsPackage conflicts between projectsUse one virtual environment per project
Not pinning versions in productionApps break when packages release incompatible updatesUse == versions in requirements.txt
Running pip freeze in a polluted environmentRequirements include unrelated packagesUse clean virtual environments per project
Installing dev tools in productionLarger attack surface and slower deploymentsSeparate requirements.txt and requirements-dev.txt
Using pip without specifying Python versionRisk of mixing up Python 3 vs system defaultUse python -m pip

By following these patterns you will be able to manage your backend project dependencies in a professional, reliable way.

Views: 8

Comments

Please login to add a comment.

Don't have an account? Register now!