
最近在帮团队搭建新的后端服务时发现很多刚接触 Python 的同学对 FastAPI 既好奇又有点无从下手。网上的资料要么太零散要么直接上复杂项目缺少一个能快速跑起来、理解核心概念的“最小可行路径”。本文就为你梳理这样一条路径用十分钟左右的时间带你从零开始完成 FastAPI 的快速入门并亲手运行起你的第一个 API。无论你是想快速验证想法还是为后续深入学习打基础这篇指南都能让你直接上手。1. FastAPI 是什么为什么选择它在开始动手之前我们先花一分钟了解一下 FastAPI 到底是什么以及它为什么能在众多 Python Web 框架中脱颖而出。FastAPI 是一个用于构建 API 的现代、快速高性能的 Web 框架。它的核心设计目标是让开发者能够用最少的代码、最直观的方式构建出高性能、生产就绪的 API。它主要解决了以下几个痛点开发速度慢传统框架配置繁琐FastAPI 基于 Python 类型提示能自动生成交互式 API 文档并减少大量重复代码。性能瓶颈基于Starlette用于 Web 微服务和Pydantic用于数据验证构建性能与 Node.js 和 Go 的框架相当。学习成本高利用 Python 3.6 的类型提示代码即文档减少了在代码、文档和调试之间切换的认知负担。常见应用场景构建微服务后端 API。快速开发数据科学或机器学习模型的推理接口。需要自动生成 OpenAPI 文档和交互式 API 界面的项目。任何对性能有要求但又希望保持 Python 开发效率的 Web 服务。简单来说如果你需要快速、优雅地构建一个 API并且希望它天生自带“使用说明书”那么 FastAPI 是一个非常值得尝试的选择。2. 环境准备与安装“工欲善其事必先利其器”。在编写第一行代码前我们需要准备好 Python 环境并安装必要的依赖。2.1 Python 版本要求FastAPI 需要Python 3.7版本。你可以通过以下命令检查你的 Python 版本python --version # 或 python3 --version如果版本低于 3.7请先升级 Python。本文所有示例均在 Python 3.8 环境下测试通过。2.2 创建虚拟环境强烈推荐为了避免项目间的依赖冲突强烈建议为每个 FastAPI 项目创建独立的虚拟环境。使用venv(Python 内置)# 1. 创建一个新目录并进入 mkdir fastapi-quickstart cd fastapi-quickstart # 2. 创建虚拟环境环境文件夹名为 venv python -m venv venv # 3. 激活虚拟环境 # 在 Windows 上 venv\Scripts\activate # 在 macOS/Linux 上 source venv/bin/activate激活后你的命令行提示符前通常会显示(venv)表示已进入虚拟环境。2.3 安装 FastAPI 及其依赖FastAPI 本身是一个轻量级框架但它运行需要一个 ASGI 服务器。最常用的是Uvicorn它是一个闪电般的 ASGI 服务器。# 在激活的虚拟环境中执行 pip install fastapi uvicorn[standard]fastapi: FastAPI 框架本身。uvicorn[standard]: ASGI 服务器[standard]后缀会额外安装一些高性能依赖如httptools,uvloop推荐安装以获得最佳性能。安装完成后可以通过pip list查看已安装的包确认fastapi和uvicorn已就位。至此环境准备完毕我们可以开始编写代码了。3. 第一个 FastAPI 应用Hello World让我们从一个最简单的例子开始感受一下 FastAPI 的简洁与强大。3.1 创建主文件在你的项目目录 (fastapi-quickstart) 下创建一个名为main.py的文件。3.2 编写代码将以下代码复制到main.py中# main.py from fastapi import FastAPI # 1. 创建一个 FastAPI 应用实例 app FastAPI() # 2. 定义一个路径操作装饰器 app.get(/) async def read_root(): # 3. 定义路径操作函数 return {message: Hello World} app.get(/items/{item_id}) async def read_item(item_id: int, q: str None): return {item_id: item_id, q: q}代码逐行解释from fastapi import FastAPI: 导入 FastAPI 类。app FastAPI(): 创建 FastAPI 应用的一个实例。这是所有应用的核心。app.get(“/”): 这是一个路径操作装饰器。它告诉 FastAPI下面的函数read_root负责处理发送到路径/的HTTP GET请求。async def read_root():: 定义了一个路径操作函数。使用async def将其定义为异步函数可以处理异步操作非必须但推荐。当有 GET 请求访问/时这个函数会被调用。return {“message”: “Hello World”}: 函数返回一个字典。FastAPI 会自动将其转换为JSON格式作为 HTTP 响应。第二个函数read_item演示了路径参数(item_id) 和查询参数(q) 的使用。item_id: int声明了参数类型FastAPI 会自动进行验证和转换。3.3 运行应用在命令行中确保你位于main.py所在的目录并且虚拟环境已激活然后运行uvicorn main:app --reload命令参数解释main:main.py文件Python 模块。app: 在main.py中创建的app FastAPI()实例。--reload: 让服务器在代码更改后自动重启。仅在开发时使用。你会看到类似下面的输出INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRLC to quit) INFO: Started reloader process [XXXXX] using statreload INFO: Started server process [XXXXX] INFO: Waiting for application startup. INFO: Application startup complete.3.4 访问你的 API访问 API 端点打开浏览器访问http://127.0.0.1:8000/。你将看到 JSON 响应{“message”: “Hello World”}。访问带参数的端点访问http://127.0.0.1:8000/items/42?qtest。你将看到{“item_id”: 42, “q”: “test”}。尝试将42换成非数字如fooFastAPI 会自动返回一个包含验证错误的 JSON 响应。访问自动生成的交互式 API 文档Swagger UI: 访问http://127.0.0.1:8000/docs。这是一个功能齐全的交互式 API 文档你可以在这里直接测试你的 API 端点无需使用 Postman 等外部工具。ReDoc: 访问http://127.0.0.1:8000/redoc。这是一个更简洁的 API 文档展示。恭喜你的第一个 FastAPI 应用已经成功运行。整个过程可能连五分钟都不到。4. 核心概念快速解析通过上面的“Hello World”我们已经接触了 FastAPI 的几个核心概念。现在让我们更系统地理解它们。4.1 路径操作装饰器与函数这是定义 API 端点的核心方式。路径URL 中域名之后的部分如/,/items/{item_id}。操作HTTP 方法如GET,POST,PUT,DELETE。装饰器如app.get(“/items/{item_id}”)它将下面的函数与特定的路径和操作绑定。路径操作函数被装饰的函数如async def read_item(...)。它处理请求并返回响应。4.2 路径参数与查询参数路径参数作为 URL 路径的一部分。使用{变量名}声明并在函数参数中接收。FastAPI 会根据声明的类型如int进行解析和验证。app.get(“/users/{user_id}”) async def read_user(user_id: int): return {“user_id”: user_id}查询参数位于 URL 的?之后以keyvalue形式出现多个参数用连接。在函数参数中声明为非路径参数即可可以设置默认值。app.get(“/items/“) async def read_items(skip: int 0, limit: int 10): # 访问 /items/?skip20limit5 return {“skip”: skip, “limit”: limit}4.3 请求体与 Pydantic 模型对于POST,PUT等需要接收客户端发送数据的请求我们使用请求体。FastAPI 强烈推荐使用Pydantic 模型来定义请求体的结构。Pydantic 模型利用 Python 类型提示来定义数据的“形状”并自动处理验证、序列化和文档生成。让我们创建一个接收 JSON 请求体的 POST 接口from fastapi import FastAPI from pydantic import BaseModel from typing import Optional app FastAPI() # 1. 定义一个 Pydantic 模型 class Item(BaseModel): name: str description: Optional[str] None price: float tax: Optional[float] None # 2. 在路径操作函数中将模型声明为参数 app.post(“/items/“) async def create_item(item: Item): # 3. 直接使用验证和转换后的数据 item_dict item.dict() if item.tax: price_with_tax item.price item.tax item_dict.update({“price_with_tax”: price_with_tax}) return item_dict代码解释定义Item类继承BaseModel并声明其属性及类型。Optional[str]表示该字段是可选的字符串类型 None是其默认值。在create_item函数中将item参数的类型声明为Item。FastAPI 会自动读取请求体JSON。转换为相应的类型如字符串转字符串数字转浮点数。验证数据。如果无效例如缺少必需的name字段将返回包含错误详情的 422 状态码。将验证后的数据提供给item参数。现在访问http://127.0.0.1:8000/docs找到POST /items/接口点击 “Try it out”输入 JSON 数据如{“name”: “Foo”, “price”: 50.2}然后执行。你会看到它成功返回了处理后的数据。4.4 响应模型你还可以使用 Pydantic 模型来声明响应的结构这有助于过滤输出字段、生成准确的 API 文档。from fastapi import FastAPI from pydantic import BaseModel app FastAPI() class ItemIn(BaseModel): # 输入模型 name: str description: str None price: float tax: float None class ItemOut(BaseModel): # 输出模型 name: str price: float price_with_tax: float None app.post(“/items/“, response_modelItemOut) async def create_item(item: ItemIn): # 内部计算逻辑 item_dict item.dict() if item.tax: item_dict[“price_with_tax”] item.price item.tax # 返回的数据会自动被 response_model 过滤和验证 return item_dict使用response_modelItemOut后即使ItemIn包含description和tax字段响应中也只会包含ItemOut中定义的字段。5. 完整实战案例简易待办事项 API现在让我们综合运用以上知识构建一个具有基本 CRUD创建、读取、更新、删除功能的简易待办事项TodoAPI。我们将使用内存中的列表来模拟数据库。5.1 项目结构fastapi-todo/ ├── main.py # 主应用文件 └── requirements.txt # 依赖文件可选内容为 fastapi uvicorn[standard]5.2 编写核心代码将以下完整代码复制到main.py# main.py from fastapi import FastAPI, HTTPException from pydantic import BaseModel from typing import List, Optional from uuid import uuid4, UUID app FastAPI(title“Todo API”, description“A simple Todo API with FastAPI”) # Pydantic 模型定义 class TodoCreate(BaseModel): “”“创建待办事项的请求体模型”“” title: str description: Optional[str] None completed: bool False class TodoUpdate(BaseModel): “”“更新待办事项的请求体模型”“” title: Optional[str] None description: Optional[str] None completed: Optional[bool] None class Todo(TodoCreate): “”“待办事项的响应模型包含唯一ID”“” id: UUID # 模拟数据库内存中的列表 todos: List[Todo] [] # 根路径 app.get(“/“) async def root(): return {“message”: “Welcome to the Todo API”, “docs”: “/docs”} # 1. 创建待办事项 (POST) app.post(“/todos/“, response_modelTodo, status_code201) async def create_todo(todo_in: TodoCreate): “”“创建一个新的待办事项”“” # 生成唯一ID todo_id uuid4() # 创建 Todo 对象将输入数据与ID合并 todo Todo(idtodo_id, **todo_in.dict()) # 保存到“数据库” todos.append(todo) return todo # 2. 获取所有待办事项 (GET) app.get(“/todos/“, response_modelList[Todo]) async def read_todos(completed: Optional[bool] None): “”“获取待办事项列表可通过 completed 查询参数过滤”“” if completed is None: return todos filtered_todos [todo for todo in todos if todo.completed completed] return filtered_todos # 3. 获取单个待办事项 (GET) app.get(“/todos/{todo_id}”, response_modelTodo) async def read_todo(todo_id: UUID): “”“根据ID获取单个待办事项”“” for todo in todos: if todo.id todo_id: return todo # 如果没找到抛出 404 错误 raise HTTPException(status_code404, detail“Todo not found”) # 4. 更新待办事项 (PUT) app.put(“/todos/{todo_id}”, response_modelTodo) async def update_todo(todo_id: UUID, todo_update: TodoUpdate): “”“根据ID更新待办事项”“” for index, todo in enumerate(todos): if todo.id todo_id: # 获取更新数据排除未提供的字段 update_data todo_update.dict(exclude_unsetTrue) # 更新找到的待办事项 updated_todo todo.copy(updateupdate_data) todos[index] updated_todo return updated_todo raise HTTPException(status_code404, detail“Todo not found”) # 5. 删除待办事项 (DELETE) app.delete(“/todos/{todo_id}”, status_code204) async def delete_todo(todo_id: UUID): “”“根据ID删除待办事项”“” for index, todo in enumerate(todos): if todo.id todo_id: todos.pop(index) return raise HTTPException(status_code404, detail“Todo not found”)5.3 运行与测试确保在项目目录下运行uvicorn main:app --reload。打开浏览器访问http://127.0.0.1:8000/docs。在 Swagger UI 中你可以依次测试每个接口POST /todos/点击 “Try it out”在 Request body 中输入{“title”: “Learn FastAPI”, “description”: “Finish the quickstart guide”}执行。你会得到包含id的响应。GET /todos/直接执行会看到刚创建的待办事项列表。尝试添加查询参数?completedfalse。GET /todos/{todo_id}将上一步响应中的id复制过来填入todo_id参数执行。PUT /todos/{todo_id}使用相同的id在 Request body 中输入{“completed”: true}执行以标记为完成。DELETE /todos/{todo_id}使用id执行删除返回状态码 204无内容。这个简单的 API 涵盖了 FastAPI 最常用的功能路径参数、查询参数、请求体、响应模型、状态码以及错误处理HTTPException。6. 常见问题与排查思路在实际开发中你可能会遇到一些常见问题。这里列出几个高频问题及其解决方案。问题现象可能原因解决思路启动失败ModuleNotFoundError: No module named ‘fastapi’1. 未安装fastapi包。2. 未在正确的虚拟环境中运行。1. 运行pip install fastapi uvicorn[standard]。2. 确认命令行提示符前有(venv)或使用which python/where python检查 Python 解释器路径。访问localhost:8000无响应1. Uvicorn 服务未成功启动。2. 防火墙或端口占用。1. 检查命令行是否有错误信息确认看到Application startup complete。2. 尝试更换端口运行uvicorn main:app --reload --port 8001。POST 请求报错422 Unprocessable Entity请求体数据不符合 Pydantic 模型定义。1. 检查 Swagger UI 或客户端发送的 JSON 格式是否正确。2. 确认字段名拼写、数据类型如stringvsnumber是否与模型匹配。3. 查看错误响应体里面有详细的验证错误信息。Swagger UI (/docs) 页面无法加载或空白网络问题或浏览器缓存。1. 检查控制台 (F12) 是否有 JS/CSS 加载错误。2. 尝试使用http://127.0.0.1:8000/docs而非localhost。3. 清除浏览器缓存或使用无痕模式。代码修改后服务器没有自动重启 (--reload失效)1. 文件未被监视。2. 某些编辑器保存方式特殊。1. 确保uvicorn命令是从包含main.py的目录运行的。2. 尝试手动停止 (CtrlC) 并重启服务。async def函数内执行了同步的耗时操作导致性能差在异步函数中阻塞了事件循环。1. 对于 I/O 密集型操作如网络请求、文件读写使用async/await兼容的库如httpx,aiofiles。2. 对于 CPU 密集型操作使用fastapi.BackgroundTasks或将其放入线程池执行。关于“用 Spring 的 RestTemplate 请求 FastAPI 报错422 Unprocessable Entity on POST”的专项排查 这个问题在跨技术栈调用时很常见。根本原因是请求的Content-Type或数据格式不匹配。确认 Content-Type确保 RestTemplate 发出的请求头包含Content-Type: application/json。确认请求体格式FastAPI 默认期望 JSON。检查 RestTemplate 发送的数据是否是有效的 JSON 字符串。使用StringEntity时确保设置了正确的 Content-Type。// Spring RestTemplate 示例 HttpHeaders headers new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); String requestBody “{\”name\”:\”Foo\”, \”price\”: 50.2}”; // 注意转义 HttpEntityString request new HttpEntity(requestBody, headers); ResponseEntityString response restTemplate.postForEntity(url, request, String.class);在 FastAPI 端调试先使用 Swagger UI 或 Postman 测试你的 FastAPI 接口确保它本身工作正常。然后在 FastAPI 的路径操作函数开头添加print(await request.json())或print(item.dict())来查看实际接收到的数据。7. 进阶配置与最佳实践掌握了基础之后了解一些进阶配置和最佳实践能让你的 FastAPI 应用更加健壮和高效。7.1 应用配置与元数据创建FastAPI实例时可以传入更多参数来配置应用from fastapi import FastAPI app FastAPI( title“我的项目API”, description“这是一个非常棒的项目API文档”, version“1.0.0”, # docs_url 和 redoc_url 可以自定义或禁用文档路径 # docs_url“/api-docs”, # redoc_urlNone, )这些信息会显示在自动生成的 API 文档中。7.2 依赖注入系统FastAPI 强大的依赖注入系统可以帮你管理共享的逻辑如数据库会话、认证、权限检查等。from fastapi import Depends, FastAPI, HTTPException, Header app FastAPI() # 定义一个依赖函数 async def verify_token(x_token: str Header(...)): if x_token ! “fake-super-secret-token”: raise HTTPException(status_code400, detail“X-Token header invalid”) return x_token # 在路径操作函数中使用依赖 app.get(“/items/“) async def read_items(token: str Depends(verify_token)): return {“token”: token, “items”: [“item1”, “item2”]}Depends会先执行verify_token函数并将其返回值注入到token参数中。如果依赖项抛出异常如HTTPException请求将在此处终止不会执行路径操作函数。7.3 后台任务对于不需要立即返回给客户端的操作如发送邮件、处理文件可以使用后台任务。from fastapi import BackgroundTasks, FastAPI app FastAPI() def write_notification(email: str, message““): # 模拟一个耗时的操作比如写日志或发邮件 with open(“log.txt”, mode“a”) as f: f.write(f“notification for {email}: {message}\n”) app.post(“/send-notification/{email}”) async def send_notification(email: str, background_tasks: BackgroundTasks): background_tasks.add_task(write_notification, email, message“some notification”) return {“message”: “Notification sent in the background”}7.4 项目结构建议对于稍大的项目建议采用模块化结构my_project/ ├── app/ │ ├── __init__.py │ ├── main.py # 创建 FastAPI app 并导入路由 │ ├── dependencies.py # 依赖项如数据库连接、认证 │ ├── models.py # Pydantic 模型 │ ├── schemas.py # 或叫 schemas.py同上 │ ├── crud.py # 数据库操作函数 │ ├── database.py # 数据库连接配置 │ ├── routers/ # 路由模块 │ │ ├── __init__.py │ │ ├── items.py │ │ └── users.py │ └── internal/ # 内部管理路由 │ ├── __init__.py │ └── admin.py ├── requirements.txt └── .env # 环境变量不要提交到版本库在app/main.py中from fastapi import FastAPI from app.routers import items, users app FastAPI() app.include_router(items.router) app.include_router(users.router)7.5 生产环境部署注意事项移除--reload生产环境绝对不要使用--reload参数。使用进程管理器使用Gunicorn(配合 Uvicorn Worker) 或Uvicorn配合Supervisor/systemd来管理进程实现自动重启和日志管理。# 使用 Gunicorn 的例子 pip install gunicorn gunicorn main:app -w 4 -k uvicorn.workers.UvicornWorker -b 0.0.0.0:8000-w 4表示启动 4 个 worker 进程。设置环境变量将密钥、数据库连接字符串等敏感信息存储在环境变量或配置文件中不要硬编码在代码里。启用日志配置适当的日志级别便于监控和排查问题。考虑反向代理在生产中通常会在 FastAPI 应用前放置一个反向代理如 Nginx 或 Traefik用于处理静态文件、SSL 终止、负载均衡等。十分钟的快速入门之旅到此结束。你已经成功搭建了第一个 FastAPI 应用理解了其核心概念并构建了一个具备 CRUD 功能的简易 API。FastAPI 的魅力在于其“约定优于配置”的理念和强大的类型提示系统这让你能用极少的代码完成大量工作。接下来你可以深入探索其官方文档学习中间件、WebSocket、数据库集成如 SQLAlchemy, Tortoise-ORM、更复杂的依赖注入、测试等高级主题将其应用到更复杂的真实项目中。