FastAPI on Localhost
FastAPI is a modern Python web framework for building APIs. It is built on Starlette (ASGI) and Pydantic, and runs via Uvicorn on port 8000 by default. FastAPI automatically generates interactive API documentation (Swagger UI at /docs and ReDoc at /redoc) from your code — no separate config file needed.
Dev server:localhost:8000
Auto docs: localhost:8000/docs · ReDoc: localhost:8000/redoc
Quick Start
# Install
pip install fastapi uvicorn
# main.py
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
@app.get("/")
def root():
return {"message": "Hello World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
return {"item_id": item_id, "q": q}
# Run
uvicorn main:app --reload
Request Body and Pydantic Models
from pydantic import BaseModel
class Item(BaseModel):
name: str
price: float
is_offer: bool = False
@app.post("/items/")
def create_item(item: Item):
return item
# FastAPI automatically validates the request body,
# shows the model in /docs, and returns 422 if validation fails
Path, Query, and Header Parameters
from fastapi import Header, Query
@app.get("/users/{user_id}/items")
def get_user_items(
user_id: int, # Path parameter
skip: int = Query(0, ge=0), # Query param with validation
limit: int = Query(10, le=100), # Query param max 100
x_token: str | None = Header(None) # Optional header
):
return {"user_id": user_id, "skip": skip, "limit": limit}
Async Endpoints
import asyncio
import httpx
@app.get("/external-data")
async def fetch_external():
async with httpx.AsyncClient() as client:
response = await client.get("https://api.example.com/data")
return response.json()
# Use async when calling other async services (DB, HTTP calls)
# Use sync def for CPU-bound work (FastAPI runs them in a thread pool)
Database with SQLAlchemy
from sqlalchemy import create_engine
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import DeclarativeBase, sessionmaker
# Async Postgres
engine = create_async_engine("postgresql+asyncpg://user:pass@localhost/db")
AsyncSessionLocal = sessionmaker(engine, class_=AsyncSession)
# Dependency
async def get_db():
async with AsyncSessionLocal() as db:
yield db
@app.get("/users/{id}")
async def get_user(id: int, db: AsyncSession = Depends(get_db)):
user = await db.get(User, id)
return user
FastAPI vs Other Python Frameworks
| Framework | Default Port | Type | Best For |
|---|---|---|---|
| FastAPI | 8000 | ASGI, async | APIs, high-performance, auto-docs |
| Django | 8000 | WSGI/ASGI, sync+async | Full-stack apps, ORM, admin panel |
| Flask | 5000 | WSGI, sync | Simple APIs, microservices, quick prototyping |
| Starlette | 8000 | ASGI, async | FastAPI's foundation, lower-level |
| Tornado | 8888 | ASGI, async | WebSockets, long polling |
Production Deployment
# Multiple workers for production
uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4
# With Gunicorn (process manager) + Uvicorn workers
pip install gunicorn
gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000
# Docker
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Troubleshooting
Port 8000 already in use: Another process is on port 8000 — check lsof -i :8000. Run on a different port: uvicorn main:app --port 8001. This commonly conflicts with Django's dev server or another FastAPI instance.
CORS errors in browser: Add the CORS middleware:
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"])