23.1 FastAPI 的面试题

FastAPI 的面试题通常从"是什么"开始,深入到"为什么"和"怎么用",最后考察在复杂场景下的工程能力。这里为你梳理了一套系统的高频面试题,并附上了参考答案和考察重点。


一、基础概念与核心优势

1. 请简述 FastAPI 的核心特点和优势。为什么它被称为"高性能"?

考察点: 对框架定位和核心价值的理解。

参考答案:

FastAPI 是一个现代、高性能的 Python Web 框架,它的核心优势主要体现在以下几点:

  • 极致的性能 :底层基于 Starlette (一个轻量级 ASGI 框架),原生支持 async/await 异步语法。在处理高并发的 I/O 密集型任务(如数据库查询、外部 API 调用)时,能高效利用单线程处理成千上万的并发连接,性能可与 Node.js 和 Go 等语言的框架相媲美。
  • 强大的类型安全与自动校验 :深度集成 Pydantic,利用 Python 的类型提示,在运行时自动对请求数据进行解析、验证和序列化。这极大地减少了手动校验代码,并保证了代码的健壮性。
  • 自动生成交互式 API 文档 :根据代码自动生成符合 OpenAPI 标准的文档,并提供 /docs (Swagger UI) 和 /redoc (ReDoc) 两种交互式界面。这保证了文档与代码的实时同步。

2. FastAPI vs Flask:为什么选择 FastAPI 而不是 Flask?

考察点: 框架选型能力。

参考答案:

  • FastAPI :基于 ASGI ,原生支持异步,配合 uvicorn 能无阻塞地处理高并发。同时借助 Pydantic 提供强大的数据校验、类型提示和自动生成 OpenAPI 文档,开发效率和可维护性更高。
  • Flask :更轻量,但原生是 WSGI 同步模型。处理高并发或 WebSocket 长连接等场景时,需要额外集成 geventQuart 等方案,增加了项目的复杂度和一致性成本。

二、核心机制深入

1. FastAPI 是如何实现依赖注入(Dependency Injection)的?

考察点: 对高级特性和解耦设计模式的理解。

参考答案:

依赖注入(DI)是一种用于解耦组件间依赖关系的设计模式。在 FastAPI 中,其实现流程如下:

  1. 定义依赖:依赖项可以是一个普通的函数或类。
  2. 使用 Depends :在路径操作函数的参数中,使用 fastapi.Depends 来标记一个参数为依赖项。
  3. 自动解析与注入 :当请求到达时,FastAPI 的 DI 系统会检查函数参数,对于被 Depends 标记的参数,它会去调用对应的依赖函数,并将返回值注入。如果依赖函数自身还有依赖,系统会递归地解析并注入,直到所有依赖被满足。

代码示例:

python 复制代码
from fastapi import FastAPI, Depends, Header, HTTPException

app = FastAPI()

# 1. 定义一个依赖项:从Header中获取并验证Token
async def verify_token(x_token: str = Header(...)):
    if x_token != "fake-super-secret-token":
        raise HTTPException(status_code=400, detail="Invalid token")
    return {"user": "user_123"} # 依赖的返回值

# 2. 在路径操作函数中使用 Depends
@app.get("/items/")
async def read_items(user_info: dict = Depends(verify_token)):
    # user_info 自动被注入
    return {"msg": "Hello User", "user": user_info}

2. FastAPI 的依赖注入和中间件有何不同?

考察点: 对框架组件职责的辨析。

参考答案:

  • 作用范围不同中间件 是全局的,所有请求和响应都会经过它,主要用于处理通用逻辑,如日志、CORS(跨域资源共享)等。依赖注入的作用域可以精细控制到单个路由或路由组。
  • 功能目的不同中间件 在请求/响应链上进行拦截和处理。依赖注入则是将业务逻辑所需的外部资源(如数据库会话、当前用户信息)以声明式的方式注入到视图函数中,实现逻辑复用和解耦。

三、异步与性能

1. 在 FastAPI 中,什么场景下使用 async def,什么场景下使用普通的 def

考察点: 对异步编程适用场景的理解。

参考答案:

  • 使用 async def :当路径操作函数内部需要调用异步 I/O 操作 时,例如:异步数据库查询(如 asyncpgdatabases)、异步 HTTP 请求(如 httpx.AsyncClient)、文件异步读写等。在这些场景下,使用 async def 可以让 FastAPI 在等待 I/O 时去处理其他请求,从而提高并发能力。
  • 使用普通的 def :如果函数内部的操作是纯 CPU 计算 ,或者使用的是同步 I/O 库 (如标准的 requests 库、同步的 SQLAlchemy),那么使用普通的 def 即可。FastAPI 会在执行线程池中自动运行这些函数,以避免阻塞主事件循环。

2. 请解释 FastAPI 技术栈中 Uvicorn、Starlette、FastAPI、Pydantic 各自负责什么?

考察点: 对框架分层架构的理解。

参考答案:

这四者构成了 FastAPI 的核心技术栈,分工明确:

  • UvicornASGI Web 服务器。它负责监听网络端口,接收 HTTP/WebSocket 连接,并按照 ASGI 规范将请求转换为对应用的调用。它类似于 Java 中的 Tomcat。
  • ASGI异步 Web 服务器网关接口协议。它是 Uvicorn 和 Starlette/FastAPI 之间的通信标准,定义了应用如何接收请求和发送响应。
  • StarletteWeb 框架底座。它提供了路由、中间件、请求/响应对象等核心 Web 功能。FastAPI 建立在 Starlette 之上,并对其进行了扩展。
  • FastAPI上层 Web 框架。它在 Starlette 的基础上,集成了 Pydantic 用于数据校验,并提供了依赖注入系统、自动生成文档等高级特性。
  • Pydantic数据校验库。它利用 Python 类型提示进行数据验证和设置管理,是 FastAPI 实现自动校验和序列化的基石。

四、工程实践与常见问题

1. 如何在 FastAPI 中处理全局异常,并返回统一的 JSON 错误格式?

考察点: 错误处理和可维护性设计。

参考答案:

可以通过添加自定义异常处理器 来实现。使用 @app.exception_handler() 装饰器来捕获特定异常或所有异常,并返回自定义的 JSON 响应。

代码示例:

python 复制代码
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse

app = FastAPI()

@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
    # 这里可以记录日志
    return JSONResponse(
        status_code=500,
        content={"code": 500, "message": "Internal Server Error", "detail": str(exc)}
    )

2. 如何对 FastAPI 应用进行单元测试?

考察点: 测试意识和实践能力。

参考答案:

FastAPI 官方推荐使用 pytest 配合 httpx 库进行测试。利用 TestClient 可以像发送真实 HTTP 请求一样测试你的 API。

代码示例:

python 复制代码
from fastapi.testclient import TestClient
from main import app # 假设你的FastAPI应用实例名为app

client = TestClient(app)

def test_read_main():
    response = client.get("/")
    assert response.status_code == 200
    assert response.json() == {"msg": "Hello World"}

五、高级与场景题(加分项)

1. 什么是 ASGI?它与 WSGI 的区别是什么?

考察点: 对底层协议的深度理解。

参考答案:

  • WSGI (Web Server Gateway Interface) :是 Python 传统的同步 Web 服务器网关接口。应用是同步的 callable,适合传统的短请求响应,但对 WebSocket、长连接、流式响应等场景支持不自然。
  • ASGI (Asynchronous Server Gateway Interface) :是 WSGI 的异步继任者。它将连接抽象为 scope(连接信息)、receive(接收消息)和 send(发送消息)的异步通道,使得框架可以处理 HTTP、WebSocket、长轮询、流式响应等多种协议。

2. 如何实现流式响应(如 SSE 或大模型逐字输出)?

考察点: 对现代 API(特别是 AI 应用)开发的理解。

参考答案:

使用 FastAPI 的 StreamingResponse 类,结合异步生成器(AsyncGenerator)来实现。这种方式非常适合大模型应用,因为 LLM 接口通常不是一次性返回,而是边生成边返回。

代码示例:

python 复制代码
from fastapi import FastAPI, Request
from fastapi.responses import StreamingResponse
import asyncio

app = FastAPI()

@app.get("/stream")
async def stream_data(request: Request):
    async def event_generator():
        for i in range(10):
            # 检测客户端是否断开连接
            if await request.is_disconnected():
                break
            yield f"data: 第 {i} 个数据块\n\n"
            await asyncio.sleep(0.5)

    return StreamingResponse(
        event_generator(),
        media_type="text/event-stream" # SSE 必须的 MIME 类型
    )

注意 :对于 Server-Sent Events (SSE),需要将 media_type 设置为 "text/event-stream",并确保消息格式符合 data: ...\n\n 的规范。


面试准备建议

对于有 4 年经验的你,面试官更看重的是原理理解架构设计能力,而非简单的 API 调用。建议重点准备:

  1. 不只是说"怎么用",而是说"为什么" :比如,回答依赖注入时,可以强调其如何实现解耦可测试性
  2. 结合你的项目经验:思考在你过去的项目中,哪些场景用到了 FastAPI 的异步特性、中间件或依赖注入,并准备好具体的案例。
  3. 关注前沿应用场景 :了解 FastAPI 在 AI 应用开发(如提供大模型 API、流式响应)中的优势。

祝你面试顺利!