Skip to content

Chapter 1 · FastAPI Overview and Environment Setup ​

Chapter goals: Understand what FastAPI is, its relationship with Starlette and Pydantic, set up the development environment, and run the first minimal app with hot reload.

1.1 What Is FastAPI ​

FastAPI is a modern, high-performance Python Web framework designed specifically for building APIs. The key to understanding it is seeing the three-layer structure:

  • Starlette: the underlying ASGI framework responsible for routing, request/response handling, middleware, and WebSocket — the Web infrastructure. FastAPI's async capability and performance come directly from it;
  • Pydantic: a data validation and serialization library (v2 core written in Rust) that turns JSON from requests into typed Python objects;
  • FastAPI itself: the "type-driven" glue layer that binds the two — write type annotations on your function signatures, and it auto-completes parameter parsing, validation, serialization, and documentation generation.
python
# A minimal FastAPI app: main.py
from fastapi import FastAPI

app = FastAPI()  # Create the app instance; all routes register on it


@app.get("/")
def read_root():
    return {"message": "Hello World"}  # Returning a dict auto-serializes to JSON

Why type annotations are "core"

All of FastAPI's magic enters through the function signature's type annotations: annotate a parameter as int and it parses and validates the integer from the path/query string; annotate as a Pydantic model and it reads from the request body; annotate the return value and it filters and serializes the output. The more precise your annotations, the more the framework does for you — this is why this course repeatedly emphasizes the Annotated pattern.

1.2 Installation ​

Install the full package with standard dependencies:

bash
python -m venv .venv && source .venv/bin/activate
pip install "fastapi[standard]"

fastapi[standard] additionally includes:

  • uvicorn: a high-performance ASGI server (this is what actually runs your app);
  • fastapi-cli: provides fastapi dev / fastapi run CLI tools;
  • Common optional dependencies (email-validator, httpx, jinja2, etc.) used in later chapters.

Verify the install:

bash
$ fastapi --version
# FastAPI 0.141.x

1.3 Starting with Hot Reload ​

Save the 1.1 code as main.py, then:

bash
$ fastapi dev main.py
 INFO    Will watch for changes in these directories: [...]
 INFO    Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
 INFO    Started reloader process [383138] using WatchFiles
 INFO    Application startup complete.

Open http://127.0.0.1:8000 to see {"message":"Hello World"}.

The relationship between these commands confuses beginners:

CommandPurposeCharacteristics
fastapi dev main.pyDevelopment modeAuto-discovers app; restarts on file changes
fastapi run main.pyProduction modeNo file watching; starts with production config
uvicorn main:app --reloadManual devfastapi dev is a wrapper around uvicorn internally

Use different commands for dev vs production

fastapi dev's reload process watches the entire directory — wasteful and a security risk in production. Use fastapi run or bare uvicorn/gunicorn for deployment (covered in Chapter 22).

If you prefer not to use the CLI, you can start manually:

python
# run_dev.py —— Programmatic equivalent of fastapi dev
import uvicorn

if __name__ == "__main__":
    uvicorn.run("main:app", host="127.0.0.1", port=8000, reload=True)
    # Note: first arg is the string "main:app", not the app object
    # Because hot reload re-imports the app in a child process via the import string

1.4 ASGI and the First Look at Sync/Async ​

FastAPI is an ASGI framework. ASGI (Asynchronous Server Gateway Interface) is the async successor to WSGI — servers and apps communicate via async messages, natively supporting WebSocket and long connections.

You only need to build one intuition now (Chapter 16 expands this in depth):

  • async def path functions execute in the event loop; ideal when internally using await for async I/O;
  • Plain def path functions are dispatched to a thread pool; they won't block other requests.
python
from fastapi import FastAPI
import time

app = FastAPI()


@app.get("/sync-slow")
def sync_slow():
    # Plain def: runs in thread pool; time.sleep won't block the event loop
    time.sleep(1)
    return {"mode": "sync"}


@app.get("/async-fast")
async def async_fast():
    # async def: runs in the event loop; must pair with async I/O to be meaningful
    import asyncio
    await asyncio.sleep(1)
    return {"mode": "async"}

❌ The most common pitfall: writing blocking calls (like time.sleep, synchronous requests.get) inside an async def — this deadlocks the entire event loop, queueing all concurrent requests.

1.5 Chapter Summary ​

  • FastAPI = Starlette (ASGI infra) + Pydantic (validation) + type annotations (magic entry point);
  • Install with pip install "fastapi[standard]" to get uvicorn + CLI + common deps;
  • fastapi dev for development (hot reload); fastapi run for production;
  • async def for async I/O; plain def for blocking calls (auto-dispatched to thread pool);
  • Never block the event loop inside async def.

🧪 随堂测验

点击你认为正确的选项。答错时会展示正确答案与原因解析。

1. What are the three layers that make up FastAPI?

2. Why should you never call time.sleep() inside an async def path function?

3. What is the difference between fastapi dev and fastapi run?

4. What does pip install "fastapi[standard]" install that pip install fastapi does not?

🛠️ Hands-On Exercises ​

  1. Install FastAPI with pip install "fastapi[standard]"; create main.py with a single GET / route returning {"hello": "world"}; run with fastapi dev main.py and verify in the browser.
  2. Deliberately write a blocking time.sleep(3) inside an async def route; open two browser tabs to the same endpoint simultaneously and observe the second request waiting.
  3. Rewrite the blocking route as a plain def; reload and verify both tabs respond concurrently.

Proceed to Chapter 2: First App and Auto-Generated Documentation.