Python生态下的微服务框架FastAPI
ccwgpt 2025-06-08 19:38 16 浏览 0 评论
FastAPI是什么
FastAPI 是一个用于构建 API 的 web 框架,使用 Python 并基于标准的 Python 类型提示。
与flask相比有什么优势
高性能:得益于uvloop,可达到与 NodeJS 和 Go 并肩的极高性能
简单:fastapi的设计的易于使用和学习。
文档完善:有官方中文文档,详细有条理,非常便于学习。
自动生成api文档:自动生成兼容OpenAPI相关开放标准的api文档
如何学习
- 最好的学习资源是官方文档,有中文版,非常详细清晰 fastapi.tiangolo.com/zh/learn/[1]
- 跟着代码亲自输入一遍
下面以 安装、获取请求数据、上传文件、中间件、跨域、后台任务 等常用功能来简单聊聊,同时介绍一个搭配 FastAPI 的高性能异步服务器 uvicorn
安装 FastAPI
安装非常简单,同安装其他依赖没什么区别。
pip install fastapi
不过FastAPI不像flask,会自带一个开发服务器,FastAPI需要额外安装ASGI服务器,官方推荐搭配 uvicorn
安装命令 pip install "uvicorn[standard]"
可选依赖
在使用不同功能时,需要额外安装一些如下依赖。
httpx jinja2 python-multipart itsdangerous pyyaml graphene uvicorn orjson ujson
可以预先通过命令 pip install "fastapi[all]" 来安装以上所有依赖。
一个简单的示例
访问首页/ 返回 hello world
访问 /users/数字根据输入的userID返回问候
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return "Hello World"
@app.get("/users/{user_id}")
def read_item(user_id: int):
return {"user_id": f'hello, you userID is {user_id}'}
打开 cmd 终端窗口,执行 uvicorn main:app --host 0.0.0.0 --port 8080, 然后浏览器访问 http://127.0.0.1:8080和 http://127.0.0.1:8080/users/123 即可看到返回的响应。
够简单吧。在这个过程中,FastAPI 将会自动执行以下操作:
- 校验 GET 请求的路径中是否含有 user_id 参数。
- 校验 GET 请求中的 user_id 的值是否为 int 类型。
- 如果不是,客户端将会收到清晰有用的错误信息。
- 自动对 JSON 进行转换或转换成 JSON。
指定模板目录和使用模板文件
FastAPI 多用于 API 开发,需要模板的场景不多,但需要时也可以支持。 要使用模板,请先安装jinja2依赖,安装命令 pip install jinja2
在使用前,先创建一个模板文件夹,并在代码中使用Jinja2Templates指定该目录,在需要返回模板响应的函数中指定模板文件名字和绑定的数据。
from fastapi import Request
from fastapi.templating import Jinja2Templates
from fastapi.responses import HTMLResponse
app = FastAPI()
templates = Jinja2Templates(directory="templates")
@app.get("/", response_class=HTMLResponse)
def home(request: Request):
return templates.TemplateResponse("index.html", {"request": request})
如上,以 Jinja2Templates(directory="templates") 指定当前模板存储于当前目录下的templates文件夹内,在返回响应中,指定使用index.html 模板,并绑定模板中可使用的数据requests
指定静态资源文件夹
同模板需要明确指定一样,静态文件夹也需要手动挂载
from fastapi.staticfiles import StaticFiles
app = FastAPI()
app.mount("/static", StaticFiles(directory="static"), name="static")
更推荐使用nginx作为前置,作为静态文件服务器,性能更高。
定义路由
创建一个路由:创建url路径装饰器,以及处理函数。
路径指的是 URL 中从第一个 / 起的后半部分,例如/,/users
定义一个绑定到/的GET方法的路由,代码如下
@app.get("/")
async def root():
return {"message": "Hello World"}
这就是一个GET 请求路由,当直接访问域名不加任何路径时,将使用这个处理,例如 http://xxxx.com/
@app.get("/")是装饰器,get指定请求方法为GET, 下方的函数是路径操作函数,用于接收请求信息并返回响应
可以返回一个 dict、list,像 str、int 一样的单个值,或者 Pydantic 模型
如果要捕获针对/的POST请求, 只需要新加一个路由,使用 @app.post('/')装饰器即可。如下
@app.post("/")
async def root():
return {"message": "Hello World"}
你也可以使用其他的操作:
@app.post()
@app.put()
@app.delete()
以及更少见的:
@app.options()
@app.head()
@app.patch()
@app.trace()
获取GET请求数据
- 路径参数:
- 在装饰器中声明路径参数:支持f''格式的路径参数定义 ,例如 @app.get('/user/{user_id}')
- 在请求中获取参数值:定义后可直接在处理函数参数上声明该参数及类型,函数体内直接使用
@app.get("/items/{user_id}")
async def read_item(user_id: int):
return {"uid": user_id}
上例中 user_id:int 声明为int型,FastAPI 自动将路径中对应的user_id字符串转为int类型并赋值给参数user_id,函数体中可直接使用
- 查询参数:
查询参数即url上的查询字符串,如xx.com/search?q=hello&page=1
函数声明中的参数,除了路径参数之外的,FastAPI均将他们当做查询参数,去获取和转为指定类型。
同样上面这个示例,额外增加2个参数,keyword:str,limit:int
@app.get("/items/{user_id}")
async def read_item(user_id: int,keyword:str,limit:int):
return {"uid": user_id,"keyword":keyword,""}
fastapi将会从url查询字符串中,例如http://xx.com/items/123?keyword=myname&limit=10
获取到函数中定义的同名参数,并转为指定的类型
设为可选参数:如果某个参数可以不存在,只需要简单的指定一个默认值None即可,如limit:int=None,当然也可以指定默认值,只需要将None改为想设置的数字,limit:int=10
Pydantic 数据模型
在使用 POST 请求获取请求体之前,需要提到 Pydantic 数据模型,这是FastAPI能简单而高效的一个重要原因.
Pydantic 是 Python 中使用最广泛的数据验证库。使用它可以非常方便的指定请求和返回的数据,全程自动json化,并自动校验正确性,极大的提高开发效率。
并且底层使用RUST开发,性能很高。
要使用它:
- 从 pydantic 中导入 BaseModel
- 创建数据模型类并继承 BaseModel
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
FastAPI将自动将该数据模型转为JSON 对象
{
"name": "Foo",
"description": "An optional description",
"price": 45.2,
"tax": 3.5
}
在POST请求中就可以直接使用它了,如示例
@app.post("/items/")
async def create_item(item: 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
在这个请求中,检测到 items 是一个数据模型类型,FastAPI就会自动从post请求体中获取模型声明的对应参数,并赋值给 item,在函数体中则可以直接使用它。比自行处理body要方便很多。
获取POST请求体
JSON body请求体/application/json
- 声明请求体参数
使用与声明查询参数相同的方式声明请求体:
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
@app.post("/items/")
async def create_item(item: Item):
return item
如上,声明了一个请求体item,类型是Item,FastAPI将自动从请求体中获取并转为Item类型的数据赋值给item
- 获取请求体中的数据
在函数中中即可直接使用 item.name item.price获取请求参数值
上述声明后,Fastapi将自动进行以下操作
以 JSON 形式读取请求体
(在必要时)把请求体转换为对应的类型
校验数据:
数据无效时返回错误信息,并指出错误数据的确切位置和内容
把接收的数据赋值给参数 item
把函数中请求体参数的类型声明为 Item,还能获得代码补全等编辑器支持
普通表单数据获取
接收的不是 JSON,而是表单字段时,要使用 Form 模块
先导入from fastapi import FastAPI,Form
声明方法依然和查询参数声明一样,在函数上以参数形式定义,不同的是必须指定默认值Form().
from fastapi import FastAPI, Form
app = FastAPI()
@app.post("/login/")
async def login(username: str = Form(), password: str = Form()):
return {"username": username}
如果没有指定,FastAPI只会将它当做查询参数来处理
获取上传文件
因为上传文件以「表单数据」形式发送。所以接收上传文件,要预先安装 pip install python-multipart
定义文件参数时使用 UploadFile 模块
先导入 from fastapi import FastAPI, File, UploadFile
声明方式一如既往,在函数中以参数定义,指定数据类型类为UploadFile
@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile):
return {"filename": file.filename}
剩下的复杂操作FastAPI会自动处理。
上述代码中的 file即是获取到的上传文件,它是一个UploadFile对象,属性如下
UploadFile 的属性如下:
filename:上传文件名字符串(str),例如, myimage.jpg;
content_type:内容类型(MIME 类型 / 媒体类型)字符串(str),例如,image/jpeg;
file: file-like[2] 对象。其实就是 Python文件,可直接传递给其他预期 file-like 对象的函数或支持库。
UploadFile 支持以下 async 方法
write(data):把 data (str 或 bytes)写入文件;
read(size):按指定数量的字节或字符(size (int))读取文件内容;
seek(offset):移动至文件 offset (int)字节处的位置;
- 例如,`await myfile.seek(0)` 移动到文件开头;
- 执行 `await myfile.read()` 后,需再次读取已读取内容时,这种方法特别好用;
close():关闭文件。
因为上述方法都是 async 方法,要搭配「await」使用。
例如读取contents = await myfile.read()
如果你的函数没有使用async声明,则不可使用await,可使用以下方法替代
contents = myfile.file.read()
设置和返回cookie
- 从请求中获取cookie
和定义路径参数、查询参数类似,只需要在函数中定义cookie参数,即可直接使用。类似
from typing import Union
from fastapi import Cookie, FastAPI
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def read_items(ads_id: Annotated[Union[str, None], Cookie()] = None):
return {"ads_id": ads_id}
当然形式有所变化,需要先从typing_extensions中导入Annotated
ads_id: Annotated[Union[str, None], Cookie()] = None 表示从cookie中取出名为ads_id的cookie的值
在声明时,必须使用 Cookie 声明 cookie 参数,否则该参数会被解释为查询参数。
Annotated 是Python中的一个装饰器(Decorator),它的作用是为函数、方法、类等对象添加额外的注释信息。这些注释信息可以包括参数和返回值的类型、文档字符串的内容、函数的调用示例等。使用 Annotated 能够帮助开发者更好地了解代码的用途和使用方式,提高代码的可读性和可维护性。
- 响应Cookies
要在响应中返回cookie,需要定义一个类型为 Response的参数,这样你就可以在这个临时响应对象中设置cookie
from fastapi import FastAPI, Response
app = FastAPI()
@app.post("/cookie-and-object/")
def create_cookie(response: Response):
response.set_cookie(key="fakesession", value="fake-cookie-session-value")
return {"message": "Come to the dark side, we have cookies"}
中间件
"中间件"是一个函数,它在每个请求被特定的路径操作处理之前,以及在每个响应返回之前工作.
- 创建中间件
要创建中间件可以在函数的顶部使用装饰器,例如 @app.middleware("http").
中间件参数接收如下参数:
- request
- 一个函数 call_next 它将接收 request 作为参数.
- 这个函数将 request 传递给相应的 路径操作.
- 然后它将返回由相应的路径操作生成的 response.
- 然后你可以在返回 response 前进一步修改它.
@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
start_time = time.time()
response = await call_next(request)
process_time = time.time() - start_time
response.headers["X-Process-Time"] = str(process_time)
return response
跨域处理
在 FastAPI 应用中使用 CORSMiddleware中间件 来配置跨域。
- 导入 CORSMiddleware。
- 创建一个允许的源列表(由字符串组成)。
- 将其作为「中间件」添加到你的 FastAPI 应用中。
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
app = FastAPI()
origins = [
"http://localhost.tiangolo.com",
"https://localhost.tiangolo.com",
"http://localhost",
"http://localhost:8080",
]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/")
async def main():
return {"message": "Hello World"}
CORS 预检请求
在复杂的请求时,需要有一个OPTIONS预检请求,这是带有 Origin 和 Access-Control-Request-Method 请求头的 OPTIONS 请求。
在这种情况下,中间件将拦截传入的请求并进行响应,出于提供信息的目的返回一个使用了适当的 CORS headers 的 200 或 400 响应。
简单后台任务
所谓后台任务,其实就是将相关数据交给另一个函数,然后立即返回,无需等待另一个函数的返回结果,适合于需要较长时间运行的任务,比如发送短信、邮件等。
也适合在异步处理函数中调用同步函数的情况。
当然如果你需要立即获得响应,那么不适合使用后台任务
后台任务使用BackgroundTasks实现
from fastapi import BackgroundTasks, FastAPI
app = FastAPI()
def write_notification(email: str, message=""):
with open("log.txt", mode="w") as email_file:
content = f"notification for {email}: {message}"
email_file.write(content)
@app.post("/send-notification/{email}")
async def send_notification(email: str, background_tasks: BackgroundTasks):
background_tasks.add_task(write_notification, email, message="some notification")
return {"message": "Notification sent in the background"}
实现步骤:
- 首先创建一个函数,实现实际执行任务的功能
- 在请求中注入 BackgroundTasks 然后调用 add_task, 添加任务和数据
.add_task() 接收以下参数:
- 在后台运行的任务函数(write_notification)。
- 应按顺序传递给任务函数的任意参数序列(email)。
- 应传递给任务函数的任意关键字参数(message="some notification")。
uvicorn 服务器
fastapi不自带web服务器,官方推荐 uvicorn 。这是一个高性能 ASGI 服务器
pip install "uvicorn[standard]"
安装后即可在命令行中启动服务 uvicorn main:app --host 0.0.0.0 --port 80
当然也可以直接从代码中启动
import uvicorn
async def app(scope, receive, send):
...
if __name__ == "__main__":
uvicorn.run("main:app", port=5000, log_level="info")
原文:https://juejin.cn/post/7396932646590627852
作者:mortimer
Reference
[1] https://fastapi.tiangolo.com/zh/learn/: https://fastapi.tiangolo.com/zh/learn/
[2] https://docs.python.org/zh-cn/3/glossary.html#term-file-like-object: https://docs.python.org/zh-cn/3/glossary.html#term-file-like-object
相关推荐
- 一个基于.Net Core遵循Clean Architecture原则开源架构
-
今天给大家推荐一个遵循CleanArchitecture原则开源架构。项目简介这是基于Asp.netCore6开发的,遵循CleanArchitecture原则,可以高效、快速地构建基于Ra...
- AI写代码翻车无数次,我发现只要提前做好这3步,bug立减80%
-
写十万行全是bug之后终于找到方法了开发"提示词管理助手"新版本那会儿,我差点被bug整崩溃。刚开始两周,全靠AI改代码架构,结果十万行程序漏洞百出。本来以为AI说没问题就稳了,结果...
- OneCode低代码平台的事件驱动设计:架构解析与实践
-
引言:低代码平台的事件驱动范式在现代软件开发中,事件驱动架构(EDA)已成为构建灵活、松耦合系统的核心范式。OneCode低代码平台通过创新性的注解驱动设计,将事件驱动理念深度融入平台架构,实现了业务...
- 国内大厂AI插件评测:根据UI图生成Vue前端代码
-
在IDEA中安装大厂的AI插件,打开ruoyi增强项目:yudao-ui-admin-vue31.CodeBuddy插件登录腾讯的CodeBuddy后,大模型选择deepseek-v3,输入提示语:...
- AI+低代码技术揭秘(二):核心架构
-
本文档介绍了为VTJ低代码平台提供支持的基本架构组件,包括Engine编排层、Provider服务系统、数据模型和代码生成管道。有关UI组件库和widget系统的信息,请参阅UI...
- GitDiagram用AI把代码库变成可视化架构图
-
这是一个名为gitdiagram的开源工具,可将GitHub仓库实时转换为交互式架构图,帮助开发者快速理解代码结构。核心功能一键可视化:替换GitHubURL中的"hub...
- 30天自制操作系统:第六天:代码架构整理与中断处理
-
1.拆开bootpack.c文件。根据设计模式将对应的功能封装成独立的文件。2.初始化pic:pic(可编程中断控制器):在设计上,cpu单独只能处理一个中断。而pic是将8个中断信号集合成一个中断...
- AI写代码越帮越忙?2025年研究揭露惊人真相
-
近年来,AI工具如雨后春笋般涌现,许多人开始幻想程序员的未来就是“对着AI说几句话”,就能轻松写出完美的代码。然而,2025年的一项最新研究却颠覆了这一期待,揭示了一个令人意外的结果。研究邀请了16位...
- 一键理解开源项目:两个自动生成GitHub代码架构图与说明书工具
-
一、GitDiagram可以一键生成github代码仓库的架构图如果想要可视化github开源项目:https://github.com/luler/reflex_ai_fast,也可以直接把域名替换...
- 5分钟掌握 c# 网络通讯架构及代码示例
-
以下是C#网络通讯架构的核心要点及代码示例,按协议类型分类整理:一、TCP协议(可靠连接)1.同步通信//服务器端usingSystem.Net.Sockets;usingTcpListene...
- 从复杂到优雅:用建造者和责任链重塑代码架构
-
引用设计模式是软件开发中的重要工具,它为解决常见问题提供了标准化的解决方案,提高了代码的可维护性和可扩展性,提升了开发效率,促进了团队协作,提高了软件质量,并帮助开发者更好地适应需求变化。通过学习和应...
- 低代码开发当道,我还需要学习LangChain这些框架吗?| IT杂谈
-
专注LLM深度应用,关注我不迷路前两天有位兄弟问了个问题:当然我很能理解这位朋友的担忧:期望效率最大化,时间用在刀刃上,“不要重新发明轮子”嘛。铺天盖地的AI信息轰炸与概念炒作,很容易让人浮躁与迷茫。...
- 框架设计并不是简单粗暴地写代码,而是要先弄清逻辑
-
3.框架设计3.框架设计本节我们要开发一个UI框架,底层以白鹭引擎为例。框架设计的第一步并不是直接撸代码,而是先想清楚设计思想,抽象。一个一个的UI窗口是独立的吗?不是的,...
- 大佬用 Avalonia 框架开发的 C# 代码 IDE
-
AvalonStudioAvalonStudio是一个开源的跨平台的开发编辑器(IDE),AvalonStudio的目标是成为一个功能齐全,并且可以让开发者快速使用的IDE,提高开发的生产力。A...
- 轻量级框架Lagent 仅需20行代码即可构建自己的智能代理
-
站长之家(ChinaZ.com)8月30日消息:Lagent是一个专注于基于LLM模型的代理开发的轻量级框架。它的设计旨在简化和提高这种模型下代理的开发效率。LLM模型是一种强大的工具,可以...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- 框架图 (58)
- flask框架 (53)
- quartz框架 (51)
- abp框架 (47)
- springmvc框架 (49)
- 分布式事务框架 (65)
- scrapy框架 (56)
- shiro框架 (61)
- 定时任务框架 (56)
- java日志框架 (61)
- mfc框架 (52)
- abb框架断路器 (48)
- beego框架 (52)
- java框架spring (58)
- grpc框架 (65)
- tornado框架 (48)
- 前端框架bootstrap (54)
- orm框架有哪些 (51)
- 知识框架图 (52)
- ppt框架 (55)
- 框架图模板 (59)
- 内联框架 (52)
- cad怎么画框架 (58)
- ssm框架实现登录注册 (49)
- oracle字符串长度 (48)