Topic 14 / 15

pip, Virtual Environments & Project Layout

~8 min read  //  Python Series  //  Coding India

The Problem Virtual Environments Solve

Project A needs Django 4.2; project B needs Django 5.1. Installed globally, they fight. A virtual environment gives each project its own private package directory and Python launcher.

python3 -m venv venv
source venv/bin/activate        # Linux/macOS  (Windows: venv\Scripts\activate)

which python                    # now points inside venv/
deactivate                      # leave the environment

Rules of thumb: one venv per project, named venv or .venv, always in .gitignore, never edited by hand.

pip Essentials

pip install requests                 # latest version
pip install "django>=5.0,<6.0"       # constrained range
pip install -U requests              # upgrade
pip uninstall requests
pip list                             # what's installed
pip show requests                    # details about one package

requirements.txt — Reproducible Installs

pip freeze > requirements.txt        # snapshot exact versions
pip install -r requirements.txt      # recreate anywhere

Commit requirements.txt; never commit venv/. Your teammate (and your server) runs two commands and has an identical environment.

pyproject.toml — the Modern Standard

New projects declare metadata and dependencies in one file:

[project]
name = "ci-shop"
version = "0.1.0"
requires-python = ">=3.12"
dependencies = [
    "django>=5.0",
    "requests",
]

[project.optional-dependencies]
dev = ["pytest", "ruff"]
pip install -e ".[dev]"     # install the project + dev tools, editable

Worth knowing: uv is the new ultra-fast drop-in replacement for pip/venv that many teams have adopted — same concepts, 10–100× faster.

A Sane Project Layout

ci-shop/
├── pyproject.toml
├── README.md
├── .gitignore              # venv/, __pycache__/, .env
├── src/
│   └── ci_shop/
│       ├── __init__.py
│       ├── cart.py
│       └── payments.py
└── tests/
    └── test_cart.py

Secrets (API keys, DB passwords) go in environment variables or a git-ignored .env file — never in code. Read them with os.environ.