Skip to main content
Advertisement

Ch 1.5 Virtual Environments and Package Management

Virtual environments and package management are essential for managing Python projects professionally. This chapter covers everything from venv to the modern uv tool used in real-world workflows.

1. Why Virtual Environments Are Necessary

Installing Python packages system-wide can cause problems.

Project A: requires Django 4.2
Project B: requires Django 3.2 ← same name, different version!
System-wide packages: Django ??? (version conflict!)

A Virtual Environment solves this problem by creating an isolated Python environment for each project.

Project A/ → .venv/ → Django 4.2
Project B/ → .venv/ → Django 3.2
Each has its own isolated environment — no conflicts!

2. venv — Python's Built-in Virtual Environment

Creating

# Run from the project directory
python3 -m venv .venv

# Directory structure
# .venv/
# ├── bin/ (macOS/Linux) or Scripts/ (Windows)
# │ ├── python3
# │ ├── pip
# │ └── activate
# ├── lib/
# │ └── python3.12/
# │ └── site-packages/
# └── pyvenv.cfg

Activating / Deactivating

# === macOS / Linux ===
source .venv/bin/activate
# Prompt changes: (.venv) user@machine:~/project$

# === Windows (CMD) ===
.venv\Scripts\activate.bat

# === Windows (PowerShell) ===
.venv\Scripts\Activate.ps1
# If you get a PowerShell execution policy error:
# Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

# === Verify Activation ===
which python3 # macOS/Linux: .venv/bin/python3
where python # Windows: .venv\Scripts\python.exe

# === Deactivate ===
deactivate

Working After Activation

# Upgrade pip after activating the virtual environment
(.venv) pip install --upgrade pip

# Install packages
(.venv) pip install requests pandas

# View installed packages
(.venv) pip list

3. pip — Python Package Manager

Basic Commands

# Install a package
pip install requests
pip install "django>=4.2" # Minimum version
pip install "django==4.2.7" # Exact version
pip install "django>=4.0,<5.0" # Version range

# Upgrade a package
pip install --upgrade requests

# Uninstall a package
pip uninstall requests
pip uninstall requests -y # Uninstall without confirmation prompt

# List installed packages
pip list
pip list --outdated # Packages with available updates

# Show package details
pip show requests
# Name: requests
# Version: 2.31.0
# Summary: Python HTTP for Humans.
# Home-page: https://requests.readthedocs.io
# ...

# List all versions of a package (from PyPI)
pip index versions django

4. requirements.txt

Manage project dependencies in a file.

Generating

# Save currently installed packages to requirements.txt
pip freeze > requirements.txt

# Example contents of requirements.txt
# Django==4.2.7
# requests==2.31.0
# pandas==2.1.3
# numpy==1.26.2

Using

# Install all packages from requirements.txt
pip install -r requirements.txt

# Reproduce the same environment in another location
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Separating Dependencies (dev / prod)

# requirements.txt — production dependencies
# Django==4.2.7
# gunicorn==21.2.0

# requirements-dev.txt — development dependencies
# -r requirements.txt # includes production dependencies
# pytest==7.4.3
# black==23.12.1
# mypy==1.7.1

# Install for development environment
pip install -r requirements-dev.txt

5. pyproject.toml — Modern Project Configuration

PEP 517/518 defines the modern Python project configuration file. It manages richer metadata than requirements.txt.

# pyproject.toml
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "my-project"
version = "1.0.0"
description = "My Python project"
requires-python = ">=3.12"

# Production dependencies
dependencies = [
"requests>=2.31.0",
"fastapi>=0.104.0",
"pydantic>=2.5.0",
]

# Optional dependency groups
[project.optional-dependencies]
dev = [
"pytest>=7.4.0",
"pytest-cov>=4.1.0",
"black>=23.12.0",
"ruff>=0.1.0",
"mypy>=1.7.0",
]
docs = [
"mkdocs>=1.5.0",
"mkdocs-material>=9.4.0",
]

# Tool configuration
[tool.black]
line-length = 88
target-version = ["py312"]

[tool.ruff]
line-length = 88
target-version = "py312"

[tool.mypy]
python_version = "3.12"
strict = true
# Install via pyproject.toml
pip install . # base dependencies
pip install ".[dev]" # including dev dependencies
pip install ".[dev,docs]" # including multiple groups

6. uv — Next-Generation Python Package Manager

uv is an ultra-fast Python package manager written in Rust. It is 10–100x faster than pip.

Installation

# macOS / Linux
curl -LsSf https://astral.sh/uv/install.sh | sh

# Windows (PowerShell)
powershell -c "irm https://astral.sh/uv/install.ps1 | iex"

# Install via pip
pip install uv

Basic uv Usage

# Create a virtual environment
uv venv # creates .venv
uv venv --python 3.12 # specify version

# Install packages (much faster than pip)
uv pip install requests
uv pip install -r requirements.txt

# Initialize a new project
uv init my-project
cd my-project

# Add dependencies (auto-updates pyproject.toml)
uv add fastapi
uv add --dev pytest black ruff

# Remove a dependency
uv remove requests

# Run the project
uv run python main.py
uv run pytest

uv Speed Comparison

# pip — slow
time pip install pandas numpy scipy matplotlib
# real: 45.3s

# uv — blazing fast (even faster with cache)
time uv pip install pandas numpy scipy matplotlib
# real: 2.1s

Pro Tips: .python-version file, ignoring .venv in git, separating dependency groups

.python-version file (auto-created when using pyenv):

# From the project directory
echo "3.12.3" > .python-version

# Or using a pyenv command
pyenv local 3.12.3

When this file is present, the specified Python version is automatically used in that directory.

Add .venv to .gitignore (virtual environments must never be committed to git):

# .gitignore
.venv/
venv/
env/
__pycache__/
*.pyc
*.pyo
*.pyd
.Python
*.egg-info/
dist/
build/
.mypy_cache/
.ruff_cache/
.pytest_cache/

Managing dependency groups with uv (recommended for production):

# pyproject.toml
[project]
name = "my-api"
dependencies = [
"fastapi>=0.104.0",
"uvicorn>=0.24.0",
"pydantic>=2.5.0",
"sqlalchemy>=2.0.0",
]

[project.optional-dependencies]
dev = ["pytest", "pytest-asyncio", "httpx", "black", "ruff", "mypy"]
prod = ["gunicorn", "sentry-sdk"]
# Development environment
uv sync --extra dev

# Production environment
uv sync --extra prod

You have mastered virtual environments and package management. Chapter 2 will take a deep dive into Python's basic data types and variables.

Advertisement