type
Post
status
Published
date
Mar 13, 2026
slug
fastapi001
summary
tags
python
FastAPI
学习笔记
category
python
icon
password
example-row
01.async/await
在 Python 中,
async def 用于定义协程函数(coroutine function)。调用协程函数会返回一个协程对象,而非立即执行函数体。协程函数的执行需要通过事件循环(event loop)调度,或通过 await 关键字等待其完成。无 await 的影响
1. 执行方式:同步执行
当协程函数内部没有使用
await 时,函数体将同步执行,不会让出控制权给事件循环。这意味着:- 函数会像普通函数一样从头到尾执行。
- 不会触发异步调度机制。
- 即使函数体包含耗时操作(如 IO),也会阻塞事件循环。
2. 性能影响:失去异步优势
异步编程的核心优势是在等待 IO 操作时让出控制权,让事件循环可以处理其他任务。如果协程函数内部没有
await,则:- 无法利用事件循环的并发处理能力。
- 耗时操作会阻塞整个应用。
- 与普通同步函数相比,没有性能提升。
3. 语法与运行:不会报错
重要的是,没有
await 的协程函数不会导致语法错误,依然可以正常运行。但会失去异步编程的意义。在 FastAPI 中的影响
- 路由函数标记为异步:FastAPI 会使用事件循环调度此函数
- 无
await的后果: - 函数体同步执行(因为没有挂起点)。
- 如果函数体包含耗时操作(如数据库查询、网络请求),会阻塞事件循环。
- 影响 API 的并发处理能力。
何时需要 await
在 FastAPI 路由函数中,以下情况需要使用
await:- 调用其他异步函数(如
await db.query(...))
- 执行 IO 操作(如文件读写、网络请求)
- 调用异步库的方法(如异步数据库驱动)
因此,是否需要
await 取决于函数内部是否有需要异步处理的操作。对于简单的参数处理和返回,无 await 是完全可以的。02.接口顺序
由于路径操作是按顺序依次运行的,因此,一定要在
/users/{user_id} 之前声明 /users/me ,否则/users/me 将把me作为 /users/{user_id}的路径参数,而不会调用到 /users/me 接口。03. 接口中包含路径的路径参数
假设路径操作的路径为
/files/{file_path}。但需要 file_path 中也包含路径,比如,home/johndoe/myfile.txt。此时,该文件的 URL 是这样的:
/files/home/johndoe/myfile.txt。OpenAPI 不支持声明包含路径的路径参数,因为这会导致测试和定义更加困难。
不过,仍可使用 Starlette 内置工具在 FastAPI 中实现这一功能。而且不影响文档正常运行,但是不会添加该参数包含路径的说明。
直接使用 Starlette 的选项声明包含路径的路径参数:
本例中,参数名为
file_path,结尾部分的 :path 说明该参数应匹配路径。如果
file_ path值为 /home/johndoe/myfile.txt ,请求的url则为` URL 是 /files//home/johndoe/myfile.txt 。04.接口可选参数与必选参数
- 将查询参数默认值设为
None即可声明可选的查询参数。
- 查询参数不声明默认值,即为必选查询参数。
- 如果为不是路径参数的参数声明了默认值,该参数也是可选的。
- FastAPI 可以识别同时声明的多个路径参数和查询参数。而且声明查询参数的顺序并不重要。因为FastAPI 通过参数名进行检测。
本例中有 3 个查询参数:
needy,必选的str类型参数。
skip,默认值为0的int类型参数。可选。
limit,可选的int类型参数。
05. 接口查询参数转换
访问:
http://127.0.0.1:8000/items/foo?short=1或
http://127.0.0.1:8000/items/foo?short=True或
http://127.0.0.1:8000/items/foo?short=true或
http://127.0.0.1:8000/items/foo?short=on或
http://127.0.0.1:8000/items/foo?short=yes或其它任意大小写形式(大写、首字母大写等),函数接收的
short 参数都是布尔值 True。否则为 False。06.请求体
函数参数按如下规则进行识别:
- 如果该参数也在路径中声明了,它就是路径参数。
- 如果该参数是(
int、float、str、bool等)单一类型,它会被当作查询参数。
- 如果该参数的类型声明为 Pydantic 模型,它会被当作请求体。
注意:
FastAPI 强制规则
POST/PUT/PATCH:Pydantic模型→ 自动解析为 请求体 (Request Body)。
GET/DELETE:GET /DELETE请求没有请求体,所有数据只能放在 URL 里。不允许 直接用Pydantic模型接收参数,因为请求时并不会自动转换为URL参数,请求时会直接报错。
- 如果GET/DELETE请求一定要用
Pydantic模型接收参数,需要配合Query使用。
- 类似GET请求用
Pydantic模型接收参数,需要配合Query使用。POST/PUT/PATCH请求如果要将单一类型参数通过json body传递,而不是查询参数,可以使用Body。
07.Annotated 用法
函数的查询参数
q: str | None = None 语义为q 是一个可以是 str 或 None 的参数,默认是 None。使用Annotated 方式实现如下:- 结合
Query实现多个条件校验。
2.在使用
Query 的同时需要把某个值声明为必填时,只需不声明默认值。下面示例为允许为None,但必填。下面示例为不允许为
None,但必填。08.查询参数列表
访问
http://localhost:8000/items/?q=foo&q=bar ,URL 的响应将会是:注意:
- 要声明类型为
list的查询参数,要显式地使用Query,否则它会被解释为请求体。
list[str]改为list,如q: Annotated[list, Query()] = [],FastAPI 会由之前检查列表内容必须为为string变成不会检查列表的内容的类型。
09.别名参数
请求示例如下:
注意,因为使用了别名,原始参数名
q 不会被自动识别,即不再可以使用q进行有效传参了。10.文档隐藏参数
声明查询参数,但在自动生成的api文档上不展示该查询参数。通过将
Query 的参数 include_in_schema 设为 False 实现。11.路径参数校验
从
fastapi 导入 Path 进行校验,用法类似查询参数使用Query进行校验。12.参数顺序问题
- Python 函数定义规则:位置参数(无默认值)必须在关键字参数(有默认值)之前。
- FastAPI 的
Path函数:即使没有显式设置默认值,Path(...)仍被视为有默认值的参数。
- 使用
Annotated,不存在触发python语法错误的问题,因为没有使用Query()或Path()作为函数参数的默认值。
- 在函数的第一个参数位置传入
*,后面所有参数都应该作为关键字参数(键值对)来调用,也被称为kwargs。即使它们没有默认值,这样也能规避顺序问题。
13.Field使用示例
Field用法上与Query、Path 、Body 相同。注意:
通常情况下,如果函数参数是一个 Pydantic 模型(如
item: Item),FastAPI 期望接收到的 JSON 格式是直接的字段:这里
Body(embed=True) 设置了 embed=True 时,FastAPI 期望请求体中包含一个以参数名(这里是 item)为键的 JSON 对象:如果函数参数存在多个Pydantic 模型,无论是否设置了
embed属性,都按embed=True 处理。期望传参:
14.使用dict传请求体
将请求体声明为使用某类型的键和其他类型值的
dict ,可以用于接收一些尚且未知的键值对。 JSON 仅支持将
str 作为键,但是 Pydantic 具有自动转换数据的功能,API 客户端只能将字符串作为键发送,Pydantic 就会对其进行转换并校验字符串内容是否仅包含整数。15.header命名问题
HTTP 标准请求头用连字符
-,但在 FastAPI 代码里,必须写成下划线 _,因为 Python 语法不允许变量名用连字符 - 。FastAPI 在定义Header参数时,会自动把下划线 _ 转换成连字符 - 去匹配请求头。极少数情况下,请求头本身就包含下划线(不标准,但可能遇到),可以用
convert_underscores=False 禁用转换:获取请求头:
- 单字段模式:
Annotated[类型, Header()]告诉 FastAPI:"这个参数的值来自请求头中的同名参数"。
- 模型模式:
Annotated[模型类, Header()]告诉 FastAPI:"创建一个这个模型的实例,用请求头中的数据填充"。
16.response_model指定返回类型
- 因为两个模型不同,如果我们将函数返回类型定为
UserOut,编辑器和工具会报返回了无效类型,因为它们是不同的类。而使用response_model可以自动转换指定的模型UserOut。
-> Any指定任意类型,等效于不写返回类型,FastAPI会放弃对返回类型的校验。
- FastAPI 接口返回只有 2 种情况:
- 返回普通数据(dict、Pydantic 模型):FastAPI 自动转 JSON。
- 返回 Response 对象(RedirectResponse、JSONResponse、HTMLResponse):直接返回给浏览器,不做处理。
- FastAPI不允许下面代码这种两种情况的返回数据联合混用。如果要支持返回数据联合混用,可以去掉
-> Response | dict或使用-> Any,禁用FastAPI对返回类型的校验。
response_model_exclude_unset=True设置响应的字段中,只保留实际赋值过的字段,不包含只有默认值的字段。- 如果有默认值的字段有过赋值动作,则为实际赋值过的字段,字段将被返回。
- 如果有默认值的字段赋值与默认值相同,则为实际赋值过的字段,字段将被返回。
response_model_include接收一个str组成的set,用于指定需要包含的字段,如果用的是list或tuple接收值,FastAPI会自动转换为set。
response_model_exclude用于指定需要排除的字段,用法同response_model_include。
response_model_exclude_unset=True优先级高于response_model_include,response_model_exclude优先级高于response_model_include。下面请求,/itemTest/返回{"name": "测试商品"},/itemTest2/返回{}。
17.异常处理
FastAPI中可以自定义异常,也可以覆盖自带的异常处理。
RequestValidationError包含其接收到的带有无效数据的请求体body。
- FastAPI 的
HTTPException错误类继承自 Starlette 的HTTPException错误类。FastAPI 的HTTPException在detail字段中接受任意可转换为 JSON 的数据,而 Starlette 的HTTPException只接受字符串。
18.更新部分字段
更新接口一般用put请求,FastAPI文档推荐更新部分字段用
patch 请求。上面代码传参
{"name": "Barz","price": 3} ,无论是改成 put 还是 post 请求,都能实现只更新传入的字段,只是推荐更新部分字段时,使用 patch 进行请求。请求返回如下:19.依赖项的执行顺序
- 装饰器依赖项(
dependencies参数中的)先执行,参数依赖项后执行。
- 装饰器依赖项之间,按声明顺序执行,参数依赖项之间同理。
- 装饰器依赖项的返回值不会传递给路径操作函数,参数依赖项的返回值会传递给路径操作函数。
上面测试代码实际执行顺序:['装饰器依赖1', '装饰器依赖2', '参数依赖1', '参数依赖2', '路由函数']。
20.带有yield的依赖项
- 带有
yield的依赖的退出代码会在响应发送给客户端之后执行。
Depends()接收一个scope参数:-
"function":在处理请求的 路径操作函数 之前启动依赖,在 路径操作函数 结束后结束依赖,但在响应发送给客户端之前。因此,依赖函数将围绕这个路径操作函数执行。 "request":在处理请求的 路径操作函数 之前启动依赖(与使用"function"时类似),但在响应发送给客户端之后结束。因此,依赖函数将围绕这个请求与响应周期执行。- 未指定且依赖包含
yield,则默认scope为"request"。 - 声明一个
scope="request"(默认)的依赖时,任何子依赖也需要有"request"的scope。 scope为"function"的依赖可以有scope为"function"和"request"的子依赖。- 任何依赖都需要能够在子依赖之前运行其退出代码,因为它的退出代码中可能还需要使用这些子依赖。
- 在带有
yield的依赖中捕获到了一个异常,除非你抛出另一个HTTPException或类似异常,否则你应该重新抛出原始异常。
示例代码中异常传播机制:
21.中间件
FastAPI创建http请求的中间件:在函数的顶部使用装饰器
@app.middleware("http") 。参数固定位 http 。- 存在多个中间件时:在
await call_next(request)之前的代码按中间件添加顺序最外层的先执行,之后的代码按最外层的最后执行。
- 如果你有使用
yield的依赖,依赖中的退出代码会在中间件之后运行。
- 作者:黄x黄
- 链接:https://hxhowl.site/article/fastapi001
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
相关文章

