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.
# 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 JSONWhy 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:
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 runCLI tools; - Common optional dependencies (
email-validator,httpx,jinja2, etc.) used in later chapters.
Verify the install:
$ fastapi --version
# FastAPI 0.141.x1.3 Starting with Hot Reload
Save the 1.1 code as main.py, then:
$ 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:
| Command | Purpose | Characteristics |
|---|---|---|
fastapi dev main.py | Development mode | Auto-discovers app; restarts on file changes |
fastapi run main.py | Production mode | No file watching; starts with production config |
uvicorn main:app --reload | Manual dev | fastapi 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:
# 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 string1.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 defpath functions execute in the event loop; ideal when internally usingawaitfor async I/O;- Plain
defpath functions are dispatched to a thread pool; they won't block other requests.
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 devfor development (hot reload);fastapi runfor production;async deffor async I/O; plaindeffor 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
- Install FastAPI with
pip install "fastapi[standard]"; createmain.pywith a singleGET /route returning{"hello": "world"}; run withfastapi dev main.pyand verify in the browser. - Deliberately write a blocking
time.sleep(3)inside anasync defroute; open two browser tabs to the same endpoint simultaneously and observe the second request waiting. - 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.