Skip to content

Commit 217afe1

Browse files
committed
post: fastapi lifespan & js coding style
1 parent a4686a4 commit 217afe1

File tree

35 files changed

+894
-147
lines changed

35 files changed

+894
-147
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
+++
2+
date = '2025-10-23T8:00:00+08:00'
3+
draft = false
4+
title = 'Code Quailty'
5+
tags = ['Javascript']
6+
+++
7+
8+
### 3.1 Debugging in the browser
9+
10+
Debugging is the process of finding and fixing errors with a script.
11+
All morden browsers and most other environments support debugging tools - a special UI in developer tools that makes debugging much easier.
12+
It also allows to trace the code step by step to see what exactly is going on.
13+
14+
#### The "Sources" panel
15+
16+
The Sources panel has 3 parts:
17+
18+
1. The **File Navigator** pane lists HTML, Javascript, CSS and other files, including images that are attatched to the page. Chrome extensions may appera here too.
19+
2. The **Code Editor** pane shows the source code.
20+
3. The **Javascript Debugging** pane is for debugging, we'll explore it soon.
21+
22+
#### Console
23+
24+
`Esc` 可以打开控制台,在其中可以输入命令,按回车执行。
25+
26+
#### Breakpoints
27+
28+
点击代码行号部分添加检查点,可以用于调试代码,暂停代码的执行。
29+
30+
也可以使用 `debuugger` 命令来暂停代码
31+
32+
```Javascript
33+
function hello(name) {
34+
let prase = 'Hello, ${name}!';
35+
36+
debugger;
37+
38+
say(prase);
39+
}
40+
```
41+
42+
#### Pause and look around
43+
44+
代码框右侧有 3 个部分:
45+
46+
1. **`Watch` - shows current values for any expressions.**
47+
监控表达式,该部分实时显示某个表达式的值
48+
49+
2. **`Call Stack` - shows the nested calls chain**
50+
调用栈,显示当前执行位置的 “函数调用轨迹”
51+
52+
3. **`Scope` - current variables**
53+
作用域,展示当前代码可访问的所有变量的地方
54+
- Local: 当前函数内部局部变量
55+
- Closure: 函数外层作用域闭包变量
56+
- Global: 全局作用域变量
57+
- this: 当前上下文绑定的对象
58+
59+
#### Logging
60+
61+
要在终端输出内容,使用 `console.log` 函数。
62+
例如输出 `0``4`
63+
64+
```Javascript
65+
for (let i = 0; i < 5; i++) {
66+
console.log("value", i)
67+
}
68+
```
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
+++
2+
date = '2025-10-24T8:00:00+08:00'
3+
draft = false
4+
title = 'Fastapi Lifespan Events'
5+
tags = ['Fastapi']
6+
+++
7+
8+
## Lifespan Events
9+
10+
通过生命周期事件可以定义在应用开启之前需要执行的代码,这意味着这些代码会在开始接收外部请求之前被执行一次。
11+
同样地,也可以定义应用在关闭的时候定义需要执行的代码,在尽力处理完所有请求后,该代码会被执行一次。
12+
13+
这对于设置需要在整个 app 的请求间共享的资源时非常有用,或者是需要进行清理工作的时候。
14+
例如,一个数据库连接池,或者加载一个共享的机器学习模型。
15+
16+
### Use Case
17+
18+
下面通过一个例子说明如何使用。
19+
20+
假如你有一个机器学习模型,并且需要让其处理请求,由于请求都共享同一个模型,因此不是一个请求对应一个模型,或一个用户一个模型。
21+
假设模型加载需要一定的时间,因为要从磁盘中读取大量的数据,因此不能每个请求都去加载一次。
22+
你可以在顶层的模块文件中定义加载,但这意味着当进行简单的自动化测试的时候,也会加载该模型,这样就会很慢。
23+
24+
这就是需要解决的问题,需要在请求响应之前加载模型,也不是在代码被加载的时候加载模型。
25+
26+
### Lifespan
27+
28+
可以通过在 `FastAPI` app 中使用 `lifespan` 参数来定义启动和关闭逻辑,以及一个 "context manager" (上下文管理器)。
29+
30+
通过下面这种方法创建一个含 `yield``function`
31+
32+
```Python
33+
from contextlib import asynccontextmanager
34+
35+
from fastapi impor FastAPI
36+
37+
def fake_answer_to_everything_ml_model(x: float):
38+
return x * 42
39+
40+
ml_models = {}
41+
42+
@asynccontextmanager
43+
async def lifespan(app: FastAPI):
44+
# Load the ML model
45+
ml_models["answer_to_everything"] = fake_answer_to_everything_ml_model
46+
yield
47+
# Clean up the ML models and release the resources
48+
ml_models.clear()
49+
50+
app = FastAPI(lifespan=lifespan)
51+
52+
@app.get("/predict")
53+
async def predict(x: float):
54+
result = ml_models["answer_to_everything"](x)
55+
return {"result": result}
56+
```
57+
58+
这里在生成器 `yield` 之前将模拟的昂贵函数放入机器学习字典中。
59+
这段代码将在应用程序接收请求之前执行,即启动阶段。
60+
61+
然后,在 `yield` 后面,卸载模型。
62+
这段改名将在完成请求之后执行,即关闭之前,这样会释放内存和 CPU 资源。
63+
64+
#### Lifespan function
65+
66+
第一件注意到的事是,定义了一个带 `yield` 的 async function,这与带 `yield` 的 Dependencies 相同。
67+
68+
```Python
69+
async def lifespan(app: FastAPI):
70+
...
71+
yield
72+
...
73+
```
74+
75+
`yield` 之前的部分会在应用开启之前执行,`yield` 之后的部分会在应用结束之后执行。
76+
77+
#### Async Context Manager
78+
79+
该函数使用 `@asynccontextmanager` 异步上下文管理器装饰,将函数转化成一个 "**async context manager**"。
80+
81+
```
82+
from contextlib import asynccontextmanager
83+
84+
@asynccontextmanager
85+
async def lifespan(app: FastAPI):
86+
...
87+
```
88+
89+
在 Python 中的 **context manager** 上下文管理器可以在 `with` 语法中使用,例如 `open()` 可以作为上下文管理器使用:
90+
91+
```Python
92+
with open("file.txt") as file:
93+
file.read()
94+
```
95+
96+
在最近的 Python 版本中,也有一个 **async context manager** 异步上下文管理器,可以通过 `async with` 使用:
97+
98+
```Python
99+
async with lifespan(app):
100+
await do_stuff()
101+
```
102+
103+
当使用上面那样创建一个(异步)上下文管理器时,实际发生的事是。
104+
在进入 `with` 块之前,会去执行 `yield` 之前的代码,退出 `with` 块之后,再去执行 `yield` 之后的代码。
105+
106+
在之前的例子中,并没有直接这样写,而是将其传递给 FastAPI 使用。
107+
108+
`FastAPI` app 的 `lifespan` 参数接受一个 **async context manager**,因此可以直接将 `lifespan` 异步上下文管理器传递给它。
109+
110+
```Python
111+
112+
@asynccontextmanager
113+
async def lifespan(app: FastAPI):
114+
...
115+
yield
116+
...
117+
118+
app = FataAPI(lifespan=lifespan)
119+
```
120+
121+
### Alternative Events (deprecated)
122+
123+
旧的语法这里就不再详细介绍了,大概下面这样使用
124+
125+
```Python
126+
@app.on_event("startup")
127+
async def startup():
128+
print("启动xxx")
129+
130+
@app.on_event("shutdown")
131+
async def shotdown():
132+
print("关闭xxx")
133+
```
134+
135+
### Technical Details
136+
137+
在 ASGI 协议规范下,这是 [Lifespan Protocol](https://asgi.readthedocs.io/en/latest/specs/lifespan.html) 的一部分,并且定义了 `startup``shutdown` 的事件。
138+
139+
要记住,这种 lifespan events 将只会在 mian application 执行,而不会在 [Sub Applications - Mounts](https://fastapi.tiangolo.com/advanced/sub-applications/) 中执行。

public/archives/index.html

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,10 +51,16 @@
5151
<span class="max-w-[4rem] md:max-w-none truncate">Home</span></a></li><li class="flex items-center gap-1 md:gap-2 min-w-0"><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>
5252
</span><span class="text-foreground flex items-center gap-0.5 md:gap-1 font-medium min-w-0 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="M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4"/></svg>
5353
<span class="max-w-[3rem] md:max-w-none truncate">Archives</span></span></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>
54-
<span>56 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>
55-
<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">54
56-
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">October 2025</h3><p class="text-muted-foreground text-xs">2
57-
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/understanding-svg-paths/ class=block>Understanding SVG Paths</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>
54+
<span>58 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>
55+
<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">56
56+
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">October 2025</h3><p class="text-muted-foreground text-xs">4
57+
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/fastapi-lifespan-events/ class=block>Fastapi Lifespan Events</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>
58+
<time datetime=2025-10-24>10-24</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>
59+
<span>3
60+
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/code-quailty/ class=block>Code Quailty</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>
61+
<time datetime=2025-10-23>10-23</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>
62+
<span>1
63+
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/understanding-svg-paths/ class=block>Understanding SVG Paths</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>
5864
<time datetime=2025-10-22>10-22</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>
5965
<span>8
6066
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/python-standrad-library-pathlib/ class=block>Python Standrad Library - pathlib</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>

0 commit comments

Comments
 (0)