尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

10分钟快速上手FastAPI:从零构建高性能Python API

10分钟快速上手FastAPI:从零构建高性能Python API 最近在帮团队搭建新的后端服务时对比了多个 Python Web 框架最终选择了 FastAPI。它凭借极简的语法、自动化的 API 文档和媲美 Node.js 的性能迅速成为构建现代 API 的热门选择。但对于刚接触的开发者面对官方文档和零散的教程往往不知从何下手容易在环境、依赖和请求验证上踩坑。本文旨在提供一个清晰、闭环的实战指南让你在十分钟内快速上手 FastAPI 的核心功能。我们将从一个最简单的“Hello World”开始逐步构建一个具备路径参数、查询参数、请求体验证和自动交互文档的完整 API。无论你是 Python 新手还是有 Flask/Django 经验想快速转型的开发者都能跟着步骤一步步实现。1. FastAPI 是什么为什么选择它在开始写代码之前我们需要理解 FastAPI 的定位和优势。这有助于我们在后续开发中更好地利用它的特性。FastAPI 是一个用于构建 API 的现代、快速高性能的 Web 框架主要基于 Python 3.6 的类型提示Type Hints标准。它并非一个全栈框架如 Django而是专注于 API 开发这使得它非常轻量和高效。它的核心优势体现在以下几个方面极致的性能FastAPI 底层基于 Starlette用于 Web 微服务和 Pydantic用于数据验证其性能与 Node.js 和 Go 的框架处于同一梯队远高于传统的 Flask 和 Django。这得益于其异步支持async/await和高效的数据处理。快速的开发体验利用 Python 类型提示FastAPI 能提供强大的编辑器支持包括自动补全和类型检查。更重要的是它能根据你的代码自动生成交互式 API 文档Swagger UI 和 ReDoc无需手动维护。更少的 Bug由于强制使用 Pydantic 进行数据验证很多由于数据类型错误、字段缺失导致的运行时错误在请求进入你的业务逻辑之前就被拦截并返回清晰的错误信息大大提高了代码的健壮性。标准化与兼容性它完全兼容并基于开放标准OpenAPI以前称为 Swagger和 JSON Schema。这意味着你生成的 API 可以轻松地与各种前端、移动端或第三方服务集成。常见应用场景微服务架构中的单个服务、为前端Vue/React或移动端提供数据的后端 API、需要高性能和实时性的应用如 WebSocket、快速原型验证。简单来说如果你需要快速构建一个高性能、易于维护且拥有漂亮文档的 RESTful APIFastAPI 是目前 Python 生态中最值得尝试的选择之一。2. 环境准备与项目初始化“工欲善其事必先利其器”。在编写第一行代码前我们需要准备好开发环境。整个过程非常简单。2.1 确保 Python 版本FastAPI 要求 Python 3.6 或更高版本。打开你的终端Windows 上是 CMD 或 PowerShellmacOS/Linux 上是 Terminal输入以下命令检查版本python --version # 或 python3 --version如果显示Python 3.6.x或更高则符合要求。如果版本过低请前往 Python 官网 下载并安装最新版本。2.2 创建虚拟环境强烈建议为每个项目创建独立的虚拟环境以避免不同项目间的依赖冲突。在你的项目目录下执行以下命令# 创建项目文件夹并进入 mkdir fastapi-quickstart cd fastapi-quickstart # 创建虚拟环境venv 是 Python 内置模块 python -m venv venv激活虚拟环境Windows (CMD/PowerShell):venv\Scripts\activatemacOS/Linux:source venv/bin/activate激活后你的命令行提示符前通常会显示(venv)表示已进入虚拟环境。2.3 安装核心依赖在激活的虚拟环境中使用 pip 安装 FastAPI 及其配套的 ASGI 服务器 Uvicorn。pip install fastapi uvicorn[standard]这里uvicorn[standard]中的[standard]表示安装包含额外性能依赖如httptools,websockets的完整版本这对于生产环境是推荐的。安装完成后可以通过pip list查看已安装的包。至此环境准备完毕总共可能只需要一两分钟。3. 第一个 FastAPI 应用Hello World让我们从一个最简单的例子开始感受 FastAPI 的便捷。3.1 创建主程序文件在项目根目录 (fastapi-quickstart) 下创建一个名为main.py的文件。这是 FastAPI 应用的常规入口文件名。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): return {item_id: item_id}代码逐行解释from fastapi import FastAPI导入 FastAPI 类。app FastAPI()创建 FastAPI 应用的一个实例。这个app对象是与框架交互的核心。app.get(“/”)这是一个路径操作装饰器。它告诉 FastAPI下面的函数read_root负责处理发送到路径/的GET请求。类似的还有app.post(),app.put(),app.delete()等。async def read_root():定义了一个路径操作函数。使用async def将其定义为异步函数可以处理异步操作以获得更好的性能。对于简单的同步操作使用def也可以。return {“message”: “Hello World”}函数返回一个字典。FastAPI 会自动将其转换为 JSON 格式作为 HTTP 响应体。第二个函数read_item定义了一个路径参数{item_id}。函数参数item_id: int使用了类型提示intFastAPI 会自动将 URL 中的这部分转换为整数并进行验证。如果传入http://localhost:8000/items/foofoo不是数字FastAPI 会自动返回一个包含错误详情的 422 状态码。3.3 运行应用在终端中确保当前目录是项目根目录且虚拟环境已激活然后运行以下命令uvicorn main:app --reload命令参数解释main指模块文件main.py不含.py后缀。app指在main.py中创建的FastAPI实例对象app。--reload让服务器在代码更改后自动重启。仅在开发时使用。如果看到类似下面的输出说明服务已成功启动INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRLC to quit) INFO: Started reloader process [12345] using WatchFiles INFO: Started server process [12346] 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将看到{“item_id”: 42}。访问自动生成的交互式文档这才是 FastAPI 的亮点访问http://127.0.0.1:8000/docs你会看到一个漂亮的 Swagger UI 界面里面列出了我们刚定义的两个接口 (/和/items/{item_id})。你可以直接在这个页面上点击 “Try it out” 按钮来测试接口无需使用 Postman 或 curl。访问备用 API 文档FastAPI 还提供了另一个文档界面 ReDoc访问http://127.0.0.1:8000/redoc即可查看。恭喜你的第一个 FastAPI 应用已经运行起来了并且拥有了自动生成的 API 文档。整个过程可能还不到五分钟。4. 核心功能快速上手接下来我们快速过一遍构建一个实用 API 所需的几个核心概念。4.1 路径参数与类型验证路径参数是 URL 路径的一部分用于标识特定资源。我们已经见过{item_id}。FastAPI 通过函数参数的类型提示进行强大的验证和转换。from fastapi import FastAPI from enum import Enum app FastAPI() # 使用 Python 枚举类定义预定义的路径参数值 class ModelName(str, Enum): alexnet alexnet resnet resnet lenet lenet app.get(/models/{model_name}) async def get_model(model_name: ModelName): # 可以直接使用枚举成员进行比较 if model_name is ModelName.alexnet: return {model_name: model_name, message: Deep Learning FTW!} if model_name.value lenet: return {model_name: model_name, message: LeCNN all the images} return {model_name: model_name, message: Have some residuals}访问/models/alexnet、/models/resnet或/models/lenet会得到不同的响应。如果尝试访问/models/invalidFastAPI 会自动返回错误说明该值不在枚举范围内。4.2 查询参数查询参数是出现在 URL 中?后面的键值对例如/items/?skip0limit10。在 FastAPI 中所有非路径参数的函数参数都会被自动解释为查询参数。from fastapi import FastAPI app FastAPI() fake_items_db [{item_name: Foo}, {item_name: Bar}, {item_name: Baz}] app.get(/items/) async def read_items(skip: int 0, limit: int 10): # skip 和 limit 都有默认值因此是可选的查询参数 return fake_items_db[skip : skip limit]访问/items/会返回前 10 项默认值。访问/items/?skip1limit2会返回从第 2 项开始的两项。如果访问/items/?skipfoofoo不是整数FastAPI 会返回 422 验证错误。4.3 请求体使用 Pydantic 模型当需要通过 POST、PUT 等方法发送数据如创建新项目时需要使用请求体。FastAPI 强烈推荐使用Pydantic 模型来定义请求体的结构。from fastapi import FastAPI from pydantic import BaseModel from typing import Optional app FastAPI() # 1. 定义数据模型 class Item(BaseModel): name: str description: Optional[str] None # 可选字段默认值为 None price: float tax: Optional[float] None # 2. 在路径操作中声明该模型为参数 app.post(/items/) async def create_item(item: Item): # FastAPI 会自动从请求体中读取 JSON 并转换为 Item 实例 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类它继承自pydantic.BaseModel。类的属性及其类型提示定义了请求体 JSON 的预期格式。在create_item函数中我们将item参数的类型声明为Item。FastAPI 会自动读取请求体JSON。转换为相应的类型str,float。验证数据。如果无效例如缺少必需的name字段或price是字符串将返回包含错误详情的 422 状态码。将验证后的数据提供给item参数。现在你可以打开http://127.0.0.1:8000/docs找到POST /items/接口点击 “Try it out”输入一个 JSON 请求体进行测试{ “name”: “Foo”, “description”: “A very nice Item”, “price”: 35.4, “tax”: 3.2 }点击 “Execute”你会看到服务器返回了验证后的数据并计算了price_with_tax。4.4 组合使用路径、查询和请求体你可以自由地将路径参数、查询参数和请求体模型组合在一起使用。app.put(“/items/{item_id}”) async def update_item(item_id: int, item: Item, q: Optional[str] None): result {“item_id”: item_id, **item.dict()} if q: result.update({“q”: q}) return result这个函数处理PUT /items/42?qsomequery这样的请求同时接收路径参数item_id、查询参数q和一个完整的 JSON 请求体。5. 处理错误与返回状态码一个健壮的 API 需要清晰地告知客户端发生了什么。5.1 使用 HTTPExceptionFastAPI 提供了fastapi.HTTPException来返回标准的 HTTP 错误响应。from fastapi import FastAPI, HTTPException app FastAPI() items {“foo”: “The Foo Wrestlers”} app.get(“/items/{item_id}”) async def read_item(item_id: str): if item_id not in items: # 抛出 404 异常并附带 detail 信息 raise HTTPException(status_code404, detail“Item not found”) return {“item”: items[item_id]}当访问/items/bar假设bar不存在时客户端会收到一个 404 状态码和 JSON 响应{“detail”: “Item not found”}。5.2 自定义响应状态码对于成功的操作你也可以显式地指定返回的状态码。from fastapi import FastAPI, status app FastAPI() app.post(“/items/”, status_codestatus.HTTP_201_CREATED) async def create_item(name: str): # 创建资源的逻辑... return {“name”: name}这里使用了status模块中的常量如HTTP_201_CREATED这比直接写数字201更清晰、更安全。6. 项目结构建议与进阶步骤对于稍大一点的项目合理的结构有助于维护。6.1 简单的项目结构fastapi-project/ ├── app/ │ ├── __init__.py │ ├── main.py # 原来的主文件现在可能只包含 app 实例和路由汇总 │ ├── dependencies.py # 依赖项如数据库会话 │ ├── models.py # Pydantic 模型 │ ├── schemas.py # 同上有时也叫 schemas │ ├── crud.py # 数据库操作函数 │ ├── database.py # 数据库连接配置 │ └── routers/ # 存放不同功能的路由文件 │ ├── __init__.py │ ├── items.py │ └── users.py ├── requirements.txt └── venv/6.2 使用 APIRouter 组织代码当路由增多时main.py会变得臃肿。使用APIRouter可以将路由分组。app/routers/items.py:from fastapi import APIRouter, HTTPException router APIRouter( prefix“/items”, # 该路由下的所有路径都会自动添加此前缀 tags[“items”], # 用于在 API 文档中分组 ) router.get(“/”) async def read_items(): return [{“name”: “Item 1”}, {“name”: “Item 2”}] router.get(“/{item_id}”) async def read_item(item_id: int): return {“item_id”: item_id, “name”: f“Item {item_id}”}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) app.get(“/”) async def root(): return {“message”: “Hello from structured app!”}这样items.py中定义的路由/和/{item_id}在最终应用中对应的路径将是/items/和/items/{item_id}并且在http://127.0.0.1:8000/docs的文档中它们会被归入 “items” 标签下。7. 常见问题与排查思路在学习和使用 FastAPI 的过程中你可能会遇到以下常见问题。问题现象可能原因解决思路启动命令报错ModuleNotFoundError: No module named ‘fastapi’未在正确的虚拟环境中安装依赖或依赖未安装成功。1. 确认终端提示符前有(venv)。2. 在虚拟环境中重新执行pip install fastapi uvicorn[standard]。访问localhost:8000连接被拒绝Uvicorn 服务未启动或启动在其它端口。1. 检查终端是否有 Uvicorn 成功启动的日志。2. 确认启动命令正确如uvicorn main:app --reload。3. 检查是否使用了--port指定了其他端口如--port 8080。自动生成的 API 文档 (/docs) 无法加载或样式错乱网络问题导致无法从 CDN 加载 Swagger UI 资源。1. 检查网络连接。2. 可以尝试使用离线文档模式安装pip install fastapi[all]或配置docs_urlNone并使用自定义文档。POST 请求返回422 Unprocessable Entity请求体的 JSON 数据格式与 Pydantic 模型不匹配。这是最常见的问题之一。1.仔细检查 API 文档 (/docs)查看该接口预期的请求体结构。2. 核对字段名拼写、数据类型如”price”: “100”字符串 vs”price”: 100数字。3. 确保没有缺少标记为必需的字段没有默认值的字段。4. 使用Optional或设置默认值来定义可选字段。异步函数 (async def) 内调用了阻塞性代码如耗时数据库查询、文件读写会阻塞整个事件循环导致性能下降。1. 对于 CPU 密集型任务使用def定义普通函数FastAPI 会在线程池中运行它。2. 对于 I/O 操作寻找该库的异步版本如asyncpg用于 PostgreSQLaiomysql用于 MySQL。3. 如果必须使用同步库可以用await asyncio.to_thread(sync_function, …)在单独线程中运行。部署到生产环境后性能不佳或崩溃使用默认的--reload模式或未配置合适的 worker 数量。1.生产环境务必移除--reload参数。2. 使用进程管理器如 Gunicorn 配合 Uvicorn Worker来管理多个工作进程。例如gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app。3. 根据服务器 CPU 核心数调整-wworker 数量。8. 生产环境部署与最佳实践将 FastAPI 应用投入生产环境需要考虑更多因素。8.1 使用 Gunicorn 作为进程管理器Linux/macOSUvicorn 本身是一个 ASGI 服务器但在生产环境中通常使用 Gunicorn 作为上层管理器来启动和管理多个 Uvicorn 工作进程提高并发能力和稳定性。首先安装 Gunicornpip install gunicorn然后使用以下命令启动gunicorn -w 4 -k uvicorn.workers.UvicornWorker main:app --bind 0.0.0.0:8000-w 4启动 4 个工作进程。通常设置为 CPU 核心数的 1-2 倍。-k uvicorn.workers.UvicornWorker指定使用 Uvicorn 的 Worker 类。--bind 0.0.0.0:8000绑定到所有网络接口的 8000 端口。8.2 安全最佳实践输入验证与消毒始终依赖 Pydantic 模型进行输入验证。对于字符串注意防范 SQL 注入和 XSS 攻击不要直接将用户输入拼接到 SQL 或 HTML 中。依赖项Dependencies利用 FastAPI 的依赖注入系统来处理共享逻辑如身份验证、数据库会话获取、权限检查等。这使代码更清晰、更可测试。环境变量管理不要将密钥、数据库连接字符串等硬编码在代码中。使用pydantic-settings或python-dotenv从环境变量或.env文件中读取配置。CORS跨域资源共享如果 API 需要被浏览器前端访问必须配置 CORS 中间件。from fastapi.middleware.cors import CORSMiddleware app.add_middleware( CORSMiddleware, allow_origins[“http://localhost:3000”], # 前端地址 allow_credentialsTrue, allow_methods[“*”], allow_headers[“*”], )关闭调试信息在生产环境中确保debug模式关闭app FastAPI(debugFalse)并避免在错误响应中泄露堆栈跟踪等敏感信息。8.3 性能优化建议使用异步数据库驱动如asyncpg(PostgreSQL),aiomysql(MySQL)。这能充分发挥 FastAPI 的异步优势。合理使用缓存对于不常变化的数据使用redis或memcached等缓存中间件。连接池确保数据库连接、HTTP 客户端等使用连接池避免频繁创建和销毁连接的开销。静态文件服务对于静态文件如图片、CSS、JS最好使用 Nginx 或 CDN 来服务而不是让 Python 应用来处理。十分钟的时间我们从零搭建了一个运行中的 FastAPI 应用理解了路径参数、查询参数、请求体模型、错误处理等核心概念并看到了自动生成的交互式文档。FastAPI 的学习曲线非常平缓其“约定优于配置”和“类型提示驱动”的理念让开发者能更专注于业务逻辑而非框架配置。要深入掌握下一步可以探索其依赖注入系统、后台任务、WebSocket 支持、中间件、SQL/NoSQL 数据库集成如 SQLAlchemy, Tortoise-ORM, MongoDB以及更复杂的身份认证与授权方案OAuth2, JWT。官方文档是极佳的学习资源结构清晰且示例丰富。
返回列表