Installation and Environment Configuration — UV Express Package Manager
A good development environment is like a fully equipped kitchen—the ingredients (dependencies) are available in a matter of seconds, the stove (server) lights up with a single click, and the recipe (project structure) is well-organized.
1. What You'll Learn
- UV Installation and Core Commands: Workflow for
uv init,uv add, anduv run - Creating the PriceTracker Project Skeleton: Directory Structure and Naming Conventions
- Uvicorn development server configurations:
--reload,--host,--port,--workers .envEnvironment Variable Management and Integration with python-dotenv- Use
uv run uvicornto start the development service with a single click
2. Alice's True Story
(1) Pain Point: pip is as slow as a snail when installing dependencies
Alice used pip to install dependencies for her FastAPI project, and it took three minutes to finish. To make matters worse, Bob on the team was using Python 3.11, while Alice was using 3.12—the version mismatch caused frequent conflicts in their virtual environments. Every time pip install -r requirements.txt runs, it's like playing the lottery—you never know if it will fail due to a version conflict with some lock file.
(2) Solution to the UV Problem
UV is a Python package manager written in Rust by the Astral team. It installs dependencies 10 to 100 times faster than pip, features built-in virtual environment management and Python version switching, and allows you to initialize a project with a single command.
# Initialize project and add FastAPI in one go
uv init pricetracker
cd pricetracker
uv add fastapi uvicorn
uv run uvicorn app.main:app --reload
(3) Revenue
Alice's dependency installation time dropped from 3 minutes to 3 seconds; Bob and Alice have identical environments (version locked to uv.lock), and CI/CD build times were reduced by 80%.
3. UV Package Manager Basics
(1) UV Core Commands Quick Reference
| Command | Function | pip Equivalent |
|---|---|---|
uv init |
Initialize the project | Manually create venv + requirements.txt |
uv add <pkg> |
Add a dependency to pyproject.toml | pip install + Manually update requirements.txt |
uv remove <pkg> |
Remove Dependency | pip uninstall + Manual Update |
uv run <cmd> |
Running Commands in a Virtual Environment | source venv/bin/activate && cmd |
uv sync |
Sync All Dependencies | pip install -r requirements.txt |
uv lock |
Lock Dependency Versions | pip freeze > requirements.txt |
uv python install 3.12 |
Install Python | pyenv install 3.12 |
(1) ▶ Example: Initializing a UV Project
# Create project directory
uv init pricetracker
cd pricetracker
# This creates:
# pricetracker/
# pyproject.toml
# .python-version
# hello.py
# .venv/ (auto-created virtual environment)
Output:
Initialized project pricetracker
(2) ▶ Example: Adding a FastAPI dependency
# Add FastAPI and Uvicorn
uv add fastapi uvicorn[standard]
# Check pyproject.toml
cat pyproject.toml
Output (excerpt from pyproject.toml):
[project]
name = "pricetracker"
version = "0.1.0"
requires-python = ">=3.11"
dependencies = [
"fastapi>=0.115.0",
"uvicorn[standard]>=0.30.0",
]
(2) Comparison of UV, pip, and Poetry
| Dimension | UV | pip | Poetry |
|---|---|---|---|
| Installation Speed | 10-100x faster | Benchmark | 2-5x faster |
| Lock File | uv.lock |
None | poetry.lock |
| Virtual Environment | Automatic Management | Manual venv |
Automatic Management |
| Python Version Management | Built-in | None | Requires pyenv |
| Configuration File | pyproject.toml |
requirements.txt |
pyproject.toml |
| Rust Core | Yes | No | No |
4. PriceTracker Project Skeleton
(1) Directory Structure Design
graph TD
Root[pricetracker/] --> App[app/]
App --> Main[__init__.py]
App --> MainPy[main.py]
App --> Api[api/]
Api --> Routes[routes/]
Routes --> Products[products.py]
Routes --> Prices[prices.py]
Routes --> Auth[auth.py]
App --> Models[models/]
App --> Schemas[schemas/]
App --> Services[services/]
App --> Core[core/]
Core --> Config[config.py]
Core --> Security[security.py]
App --> Db[db.py]
Root --> Tests[tests/]
Root --> Alembic[alembic/]
Root --> Docker[docker/]
Root --> Env[.env]
Root --> Pyproject[pyproject.toml]
| Table of Contents | Responsibilities | Description |
|---|---|---|
app/ |
Main App Package | All Business Code |
app/api/routes/ |
Routing Module | Break Down Endpoints by Function |
app/models/ |
SQLAlchemy Models | Database Table Mappings |
app/schemas/ |
Pydantic Models | Request/Response Validation |
app/services/ |
Business Logic | Storage Layer and Service Layer |
app/core/ |
Core Configuration | Configuration, Security, Dependencies |
tests/ |
Testing | pytest test suite |
alembic/ |
Database Migration | Alembic Migration Scripts |
docker/ |
Container Configuration | Dockerfile + Compose |
(1) ▶ Example: Creating a Project Skeleton
# Create all directories
mkdir -p app/api/routes app/models app/schemas app/services app/core
mkdir -p tests alembic docker
# Create __init__.py files
touch app/__init__.py app/api/__init__.py app/api/routes/__init__.py
touch app/models/__init__.py app/schemas/__init__.py
touch app/services/__init__.py app/core/__init__.py
touch tests/__init__.py
Output:
CONTAINER ID IMAGE STATUS
abc123 latest Up 2 hours
(2) ▶ Example: Minimal FastAPI Application app/main.py
from fastapi import FastAPI
app = FastAPI(
title="PriceTracker API",
description="SaaS price tracking service for e-commerce",
version="0.1.0",
)
@app.get("/health")
async def health_check():
return {"status": "healthy", "service": "pricetracker"}
Output:
# Function defined successfully
5. Uvicorn Development Server
(1) Uvicorn Key Parameters
| Parameter | Default Value | Description |
|---|---|---|
--host |
127.0.0.1 |
Listening address; 0.0.0.0 allows external access |
--port |
8000 |
Listening Port |
--reload |
False |
Automatic restart upon file changes (for development use only) |
--reload-dir |
. |
Directories to monitor; multiple entries allowed |
--workers |
1 |
Number of worker processes (for production use; conflicts with --reload) |
--log-level |
info |
Log Level |
(1) ▶ Example: Starting in Development Mode
# Start with hot reload - auto restart on code changes
uv run uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
Output:
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
INFO: Started reloader process
INFO: Started server process
INFO: Waiting for application startup.
INFO: Application startup complete.
(2) ▶ Example: Starting Production Mode
# Production: multiple workers, no reload
uv run uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 4
Output:
# Command executed successfully
(2) Comparison of Uvicorn Configurations for Development vs. Production
| Configuration | Development Environment | Production Environment |
|---|---|---|
--reload |
On | Off |
--workers |
1 | Number of CPU cores x 2 + 1 |
--host |
127.0.0.1 | 0.0.0.0 |
--log-level |
debug | info/warning |
| Front-end proxy | None | Nginx/Traefik |
6. Environment Variable Management
(1) The .env File and python-dotenv
Environment variables are a core principle of the 12-Factor App; sensitive configurations (such as database passwords and JWT keys) must never be hard-coded.
(1) ▶ Example: Creating a .env file
# .env - NEVER commit this file to git!
APP_NAME=PriceTracker
DEBUG=true
DATABASE_URL=postgresql+asyncpg://pricetracker:secret@localhost:5432/pricetracker
REDIS_URL=redis://localhost:6379/0
SECRET_KEY=your-super-secret-key-change-in-production
ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=30
Output:
// Execution Successful
(2) ▶ Example: Pydantic Settings Reading Environment Variables
# app/core/config.py
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
app_name: str = "PriceTracker"
debug: bool = False
database_url: str = "postgresql+asyncpg://localhost/pricetracker"
redis_url: str = "redis://localhost:6379/0"
secret_key: str = "change-me-in-production"
algorithm: str = "HS256"
access_token_expire_minutes: int = 30
model_config = {"env_file": ".env", "env_file_encoding": "utf-8"}
settings = Settings()
Output:
# Execution Successful
(3) ▶ Example: Using Configuration in FastAPI
# app/main.py
from fastapi import FastAPI
from app.core.config import settings
app = FastAPI(
title=settings.app_name,
debug=settings.debug,
)
@app.get("/info")
async def app_info():
return {
"app": settings.app_name,
"debug": settings.debug,
"database": settings.database_url.split("@")[-1], # Hide credentials
}
Output:
# Function defined successfully
(2) Essential Items for .gitignore
# Add to .gitignore
.env
.env.local
.env.production
.venv/
__pycache__/
*.pyc
| Document | Submitted | Reason |
|---|---|---|
.env |
No | Contains sensitive information |
.env.example |
Yes | Team Reference Template |
uv.lock |
Yes | Lock dependency versions |
pyproject.toml |
Yes | Project Configuration |
7. Comprehensive Example
Combining UV package management, Pydantic Settings configuration, and Uvicorn startup, this guide demonstrates the complete process from project initialization to service deployment.
# pyproject.toml dependencies: fastapi, uvicorn, pydantic-settings
from fastapi import FastAPI
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
app_name: str = "PriceTracker"
debug: bool = False
database_url: str = "postgresql+asyncpg://user:pass@localhost/pricetracker"
model_config = {"env_file": ".env"}
settings = Settings()
app = FastAPI(title=settings.app_name, debug=settings.debug)
@app.get("/health")
async def health():
return {"status": "ok", "app": settings.app_name}
@app.get("/info")
async def info():
return {"app": settings.app_name, "debug": settings.debug}
# Start: uv run uvicorn app.main:app --reload
Output:
GET /health → {"status":"ok","app":"PriceTracker"}
GET /info → {"app":"PriceTracker","debug":false}
❓ FAQ
uv.lock and virtual environments; using pip alongside it may cause dependency conflicts. Stick to the uv add/uv run workflow.powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex".📖 Summary
- UV is written in Rust; it installs dependencies 10 to 100 times faster than pip and includes built-in virtual environments and Python version management.
- The PriceTracker project uses a layered architecture consisting of five layers: api/routes, models, schemas, services, and core
- Uvicorn uses
--reloadfor hot reloading in development and--workersfor multi-process operation in production .env+ Pydantic Settings: Manage environment variables; never hard-code sensitive configurationsuv run uvicorn app.main:app --reloadLaunch a full development environment with a single command
📝 Exercises
- Basic Exercise (Difficulty ⭐): Create a project using
uv init, add the FastAPI and Uvicorn dependencies, and run your first "Hello World" endpoint. Hint:uv add fastapi uvicorn - Advanced Exercise (Difficulty: ⭐⭐): Create the directory structure for the PriceTracker project, write the
app/main.pyendpoint that includes the/healthendpoint, and useuv run uvicornto start and verify it. Hint: Refer to the directory structure diagram in this article. - Challenge (Difficulty: ⭐⭐⭐): Use Pydantic Settings to create a configuration class that reads files from the
.envfile, readDATABASE_URLandSECRET_KEY, and return the application name at the/infoendpoint (without exposing the secret). Hint:pip install pydantic-settings, i.e.,uv add pydantic-settings
---|



