Python Tutorial
Introduction to FastAPI
FastAPI is a modern Python framework for building web APIs — the back ends that mobile apps, React front ends and other services talk to. You describe each endpoint with an ordinary Python function and type hints; FastAPI uses those hints to parse and validate requests, convert responses to JSON, and generate interactive documentation automatically.
It is fast to write, fast to run (it is built on the ASGI toolkit Starlette and the validation library Pydantic), and has become one of the most popular Python web frameworks alongside Django and Flask. This lesson explains how web APIs work, sets up a project, builds a first API and explores the automatic docs.
How a Web API Works
A client sends an HTTP request with a method (GET read, POST create, PUT/PATCH update, DELETE remove), a path such as /books/42, optional query parameters (?page=2), headers and sometimes a JSON body. The server replies with a status code (200 OK, 201 Created, 404 Not Found, 422 validation error, 500 server error), headers and usually a JSON body. A REST API organises these around resources: GET /books, POST /books, GET /books/42, DELETE /books/42.
Python Web Frameworks
- FastAPI — APIs first, type-hint driven, async support, automatic OpenAPI docs.
- Flask — a small, flexible micro-framework; you choose the extras.
- Django — "batteries included": ORM, admin site, auth, templates; ideal for full websites.
- Older frameworks use WSGI (one request per worker thread); FastAPI uses ASGI, which also supports
async, WebSockets and long-lived connections.
Setting Up and Running
Create a virtual environment and run pip install "fastapi[standard]", which installs FastAPI plus the Uvicorn server and the fastapi command-line tool. fastapi dev main.py starts a development server with auto-reload at http://127.0.0.1:8000; fastapi run main.py starts it for production. Visit /docs for the interactive Swagger UI, where you can try every endpoint, /redoc for reference docs, and /openapi.json for the machine-readable OpenAPI schema.
Path Operations
An endpoint is a path operation: a decorator naming the HTTP method and path — @app.get("/"), @app.post("/books") — above a function that returns data. Return a dict, list, number, string, Pydantic model or dataclass and FastAPI converts it to JSON. Functions can be plain def (FastAPI runs them in a thread pool) or async def (when you await async libraries). In these lessons, TestClient sends requests to the app directly, so each example prints real responses without starting a server.
Examples
Install FastAPI and run the development server
python -m venv .venv
.venv\Scripts\activate # Windows (macOS/Linux: source .venv/bin/activate)
pip install "fastapi[standard]"
fastapi dev main.py # auto-reloading development server
# Open http://127.0.0.1:8000/docs -> interactive Swagger UI
# Open http://127.0.0.1:8000/redoc -> ReDoc reference documentation
curl http://127.0.0.1:8000/
INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO Started reloader process using WatchFiles
{"message":"Hello from FastAPI"}
A first API (main.py) called with TestClient
# main.py
import asyncio
from fastapi import FastAPI
from fastapi.testclient import TestClient
app = FastAPI(title="Webnest Bookstore API", version="1.0.0")
@app.get("/")
def home():
return {"message": "Hello from FastAPI"}
@app.get("/books")
def list_books():
return [{"id": 1, "title": "Python Basics"}, {"id": 2, "title": "Deep Python"}]
@app.get("/slow")
async def slow():
await asyncio.sleep(0.1) # e.g. waiting for another service
return {"done": True}
client = TestClient(app) # sends requests straight to the app
response = client.get("/")
print(response.status_code, response.json())
print(response.headers["content-type"])
print(client.get("/books").json())
print(client.get("/slow").json())
missing = client.get("/authors")
print(missing.status_code, missing.json())
200 {'message': 'Hello from FastAPI'}
application/json
[{'id': 1, 'title': 'Python Basics'}, {'id': 2, 'title': 'Deep Python'}]
{'done': True}
404 {'detail': 'Not Found'}
The automatically generated OpenAPI schema
from fastapi import FastAPI
from fastapi.testclient import TestClient
app = FastAPI(title="Webnest Bookstore API", version="1.0.0")
@app.get("/books", summary="List all books", tags=["books"])
def list_books():
"""Return every book in the catalogue."""
return []
@app.post("/books", tags=["books"])
def create_book():
return {}
schema = TestClient(app).get("/openapi.json").json()
print(schema["openapi"], "|", schema["info"])
for path, operations in schema["paths"].items():
for method, details in operations.items():
print(method.upper(), path, "->", details["summary"], details["tags"])
3.1.0 | {'title': 'Webnest Bookstore API', 'version': '1.0.0'}
GET /books -> List all books ['books']
POST /books -> Create Book ['books']
Common Mistakes
- Installing plain "fastapi" and then missing the fastapi CLI and Uvicorn — install "fastapi[standard]".
- Using fastapi dev (auto-reload, debug-friendly) in production instead of fastapi run.
- Declaring async def endpoints and then calling blocking code (time.sleep, requests, a sync DB driver) inside them, which stalls the server.
- Naming the file fastapi.py, which shadows the real package.
- Returning objects FastAPI cannot serialise (open files, custom classes without a model).
Key Points to Remember
- FastAPI builds APIs from type-hinted functions and validates everything automatically.
- Path operations: @app.get/post/put/patch/delete("/path") above a function that returns data.
- fastapi dev main.py for development; /docs and /redoc give free interactive documentation.
- Use async def only with awaitable libraries; plain def is fine and runs in a thread pool.
- TestClient calls the app directly — ideal for learning and for automated tests.
Practice the examples
Change an input, predict the result, then compare it with the output. Explain why the result changes.
Use your local project environment for these examples. Codelab currently runs Python and HTML/CSS/JavaScript; framework examples may need project dependencies.