Skip to content

Commit 89fe45c

Browse files
committed
fastapi post
1 parent 9a00dc1 commit 89fe45c

File tree

14 files changed

+600
-22
lines changed

14 files changed

+600
-22
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
欢迎访问我的博客: [https://starslayerx.github.io/](https://starslayerx.github.io/)
22

3-
配置地址[Config docs](https://hugo-narrow-docs.vercel.app/)
3+
配置地址: [Blog config docs](https://hugo-narrow-docs.vercel.app/)
44

55
- 本地调试命令
66
```

content/posts/how-fastapi-works.md

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
+++
2+
date = '2025-08-04T13:30:28+08:00'
3+
draft = false
4+
title = 'How FastAPI Works'
5+
+++
6+
FastAPI 的工作原理: 从 routing 到 lifecycle 以及在现实中的使用
7+
8+
### Fastapi
9+
Fastapi 是一个现代的 Python Web 框架, 注重**高性能****开发者效率**. 旨在帮助开发者编写结构清晰、可靠的API, 同时尽量减少样板代码 (boilerplate)
10+
11+
其由以下两个库驱动:
12+
- **Starlette**: 负责 Web 服务器逻辑、路由、中间件和异步能力
13+
- **Pydantic**: 基于 Python 类型提示, 处理数据验证、解析和序列化
14+
15+
此外, Fastapi 还有输入验证、基于 Swagger UI 的自动文档生成和代码清晰化的基础
16+
17+
18+
### API 请求周期
19+
Fastapi 的请求生命周期如下
20+
```
21+
客户端请求 (Client Request)
22+
23+
FastAPI App
24+
25+
中间件(Middleware)
26+
27+
路由匹配 (Route Matching)
28+
29+
依赖注入(Dependency Injection)
30+
31+
输入验证 (Input Validation)
32+
33+
端点函数 (Endpoint)
34+
35+
响应序列化 (Response Serialization)
36+
37+
客户端响应 (Client Response)
38+
```
39+
1. 请求首先进入 FastAPI 应用 (本质就是一个 Starlette 应用)
40+
2. 所有中间件优先执行 (如: 日志、错误处理、CORS等)
41+
3. 路由器检查路径和方法, 找到对应的处理函数
42+
4. FastAPI 使用`Depends`解析依赖
43+
5. 使用 Pydantic 自动解析并验证输入数据
44+
6. 执行端点函数, 参数验证完毕
45+
7. 返回结果被序列化为合适的响应格式 (JSON)
46+
8. 响应返回给客户端
47+
48+
### 路由 Router
49+
1. 在应用对象上定义
50+
适合小项目或原型验证
51+
```python
52+
def read_item():
53+
return {"item_id": item_id}
54+
```
55+
2. 使用 APIRouter 模块化
56+
适合大项目
57+
```python
58+
from fastapi import FastAPI
59+
60+
router = APIRouter(prefix="/users", tags=["users"])
61+
62+
@router.get("/{user_id}")
63+
def get_user(user_id: int):
64+
return {"user_id": user_id}
65+
```
66+
使用`APIRouter`可以将相关的端点分组, 添加前缀和标签, 保持代码结构清晰模块化
67+
68+
当某个请求与端点匹配时, FastAPI 内部执行一下步骤:
69+
1. Starlette 找到对应路由, 并创建一个`APIRouter`实例
70+
2. FastAPI 使用`get_router_header()`包装端点函数并解析依赖
71+
3. 使用 Pydantic 或基本类型对请求数据解析与验证
72+
4. 装饰函数被调用, 传入验证后的参数
73+
5. 返回值被序列化为响应对象
74+
75+
### 依赖注入: 干净、可复用的逻辑
76+
FastAPI 有一个轻量且强大的依赖注入系统, 可以进行数据库链接、身份验证信息或配置信息等
77+
```python
78+
from fastapi import Depends
79+
80+
def get_db():
81+
db = create_db_session()
82+
try:
83+
yield db
84+
finally:
85+
db.close()
86+
87+
@app.get("/items/")
88+
def read_items(db=Depends(get_db)):
89+
return db.query(item).all()
90+
```
91+
使用`Depends`, FastAPI 会负责调用`get_db`, 处理生成器生命周期, 并将结果注入到函数中
92+
93+
94+
### 原生支持异步 (Async)
95+
不同于一些后加入 async 的框架, FastAPI 一开始就设计为支持 async/await
96+
```python
97+
from fastapi import FastAPI
98+
import asyncio
99+
100+
app = FastAPI()
101+
102+
@app.get("/hi")
103+
async def greet():
104+
await asyncio.sleep(1)
105+
return "Hello? World?"
106+
```
107+
当 fastapi 收到 `/hi` 这个 URL 的 GET 请求时,会自动调用 async greet(), 无需在任何地方添加 await
108+
109+
但是, 对于其他的 async def 函数, 调用的时候必须在前面加上 await
110+
111+
> FastAPI 会运行一个异步事件循环,用于执行异步路径函数(async path functions),同时也会使用一个线程池来处理同步函数(synchronous path functions), 这样就不需要手动调用 `asyncio.gather()``asyncio.run()` 之类的方法
112+
113+
114+
### 示例: CURD API
115+
```python
116+
from fastapi import FastAPI
117+
from pydantic import BaseModel
118+
119+
app = FastAPI()
120+
121+
class Item(BaseModel):
122+
name: str
123+
description: str = None
124+
price: float
125+
tax: float = None
126+
127+
@app.post("/items/")
128+
async def create_item(item: Item):
129+
total = item.price + (item.tax or 0)
130+
return {"name": item.name, "total_price": total}
131+
132+
@app.get("/")
133+
def read_root():
134+
return {"message": "FastAPI is working!"}
135+
```
136+
137+
运行
138+
```
139+
uvicorn main:app --reload
140+
```
141+
142+
- 还可以使用 Gunicorn 部署4个 Uvicorn 异步服务
143+
```
144+
gunicorn main:app --workers 4 --worker-class \
145+
uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000
146+
```
147+
实际上也可以直接诶使用 uvicorn 运行多个进程, 但是这样无法进行进程管理,因此使用 gunicorn 的方法一般更多被使用
148+
149+
### 性能提升
150+
如果 API 返回大量数据, 使用 ORJSON 加快序列化速度
151+
```python
152+
from fastapi import FastAPI
153+
from fastapi.responses import ORJSONResponse
154+
155+
app = FastAPI(default_response_class=ORJSONResponse)
156+
```

public/archives/_index.fr/index.html

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,13 @@
5353
</a><span class="text-muted-foreground/50 flex-shrink-0"><svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/></svg></span>
5454
<span class="text-foreground flex items-center gap-0.5 md:gap-1 font-medium min-w-0"><svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/></svg>
5555
<span class="max-w-[8rem] md:max-w-[16rem] lg:max-w-none truncate">Archives</span></span></div></li></ol></nav><header class=mb-8><div class="mb-4 flex items-center gap-3"><svg class="h-6 w-6" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4"/></svg><h1 class="text-foreground text-3xl font-bold">Archives</h1></div><p class="text-muted-foreground mb-6">Browse all articles in chronological order and discover what interests you.</p><div class="text-muted-foreground flex items-center gap-4 text-sm"><div class="flex items-center gap-1"><svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"/></svg>
56-
<span>1 posts total</span></div><div class="flex items-center gap-1"><svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5A2 2 0 003 7v12a2 2 0 002 2z"/></svg>
57-
<span>Timeline view</span></div></div></header><div class=relative><div class="bg-border absolute top-0 bottom-0 left-4 w-0.5"></div><div class=mb-12><div class="relative mb-8 flex items-center"><div class="bg-primary absolute left-0 z-10 flex h-8 w-8 items-center justify-center rounded-full"><svg class="h-4 w-4 text-primary-foreground" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5A2 2 0 003 7v12a2 2 0 002 2z"/></svg></div><div class=ml-12><h2 class="text-foreground text-2xl font-bold">2025</h2><p class="text-muted-foreground text-sm">1
58-
posts</p></div></div><div class="relative mb-8"><div class="relative mb-4 flex items-center"><div class="bg-accent border-background absolute left-2 z-10 h-4 w-4 rounded-full border-2"></div><div class=ml-12><h3 class="text-foreground text-lg font-semibold">August 2025</h3><p class="text-muted-foreground text-xs">1
59-
posts</p></div></div><div class="ml-12 space-y-3"><article class="group bg-card border-border hover:bg-accent/50 rounded-lg border p-4 transition-all duration-300"><div class="flex items-center justify-between gap-4"><div class="min-w-0 flex-1"><h4 class="text-foreground group-hover:text-primary mb-3 font-medium transition-colors duration-200"><a href=/posts/executing-arbitrary-python-code-from-a-comment/ class=block>Executing arbitrary Python code from a comment</a></h4><div class="text-muted-foreground flex items-center gap-4 text-xs"><div class="flex items-center gap-1"><svg class="h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5A2 2 0 003 7v12a2 2 0 002 2z"/></svg>
56+
<span>2 posts total</span></div><div class="flex items-center gap-1"><svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5A2 2 0 003 7v12a2 2 0 002 2z"/></svg>
57+
<span>Timeline view</span></div></div></header><div class=relative><div class="bg-border absolute top-0 bottom-0 left-4 w-0.5"></div><div class=mb-12><div class="relative mb-8 flex items-center"><div class="bg-primary absolute left-0 z-10 flex h-8 w-8 items-center justify-center rounded-full"><svg class="h-4 w-4 text-primary-foreground" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5A2 2 0 003 7v12a2 2 0 002 2z"/></svg></div><div class=ml-12><h2 class="text-foreground text-2xl font-bold">2025</h2><p class="text-muted-foreground text-sm">2
58+
posts</p></div></div><div class="relative mb-8"><div class="relative mb-4 flex items-center"><div class="bg-accent border-background absolute left-2 z-10 h-4 w-4 rounded-full border-2"></div><div class=ml-12><h3 class="text-foreground text-lg font-semibold">August 2025</h3><p class="text-muted-foreground text-xs">2
59+
posts</p></div></div><div class="ml-12 space-y-3"><article class="group bg-card border-border hover:bg-accent/50 rounded-lg border p-4 transition-all duration-300"><div class="flex items-center justify-between gap-4"><div class="min-w-0 flex-1"><h4 class="text-foreground group-hover:text-primary mb-3 font-medium transition-colors duration-200"><a href=/posts/how-fastapi-works/ class=block>How FastAPI Works</a></h4><div class="text-muted-foreground flex items-center gap-4 text-xs"><div class="flex items-center gap-1"><svg class="h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5A2 2 0 003 7v12a2 2 0 002 2z"/></svg>
60+
<time datetime=2025-08-04>08-04</time></div><div class="flex items-center gap-1"><svg class="h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3A9 9 0 113 12a9 9 0 0118 0z"/></svg>
61+
<span>3
62+
min</span></div></div></div></div></article><article class="group bg-card border-border hover:bg-accent/50 rounded-lg border p-4 transition-all duration-300"><div class="flex items-center justify-between gap-4"><div class="min-w-0 flex-1"><h4 class="text-foreground group-hover:text-primary mb-3 font-medium transition-colors duration-200"><a href=/posts/executing-arbitrary-python-code-from-a-comment/ class=block>Executing arbitrary Python code from a comment</a></h4><div class="text-muted-foreground flex items-center gap-4 text-xs"><div class="flex items-center gap-1"><svg class="h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5A2 2 0 003 7v12a2 2 0 002 2z"/></svg>
6063
<time datetime=2025-08-04>08-04</time></div><div class="flex items-center gap-1"><svg class="h-3 w-3" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3A9 9 0 113 12a9 9 0 0118 0z"/></svg>
6164
<span>4
6265
min</span></div></div></div></div></article></div></div></div></div></main><footer class="mx-auto max-w-4xl px-4 py-8"><div class="px-6 py-6"><nav class=mb-6><div class="flex flex-wrap items-center justify-center gap-1"><a href=/ class="nav-link hover:text-primary hover:bg-primary/10 text-muted-foreground flex items-center gap-2 rounded-lg px-4 py-2 text-sm font-medium transition-all duration-300 hover:scale-105"><svg class="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-label="About"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7A4 4 0 118 7a4 4 0 018 0zm-4 7a7 7 0 00-7 7h14a7 7 0 00-7-7z"/></svg>

0 commit comments

Comments
 (0)