Python生态下的微服务框架FastAPI
ccwgpt 2025-06-08 19:38 3 浏览 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
相关推荐
- go-admin开源项目,快速搭建一个管理后台系统,直接二次开发上线
-
#头条创作挑战赛#目录1,关于go-admin2,使用go-admin进行构建3,使用go-admin进行数据库,后端初始化4,下载前端代码,进行node编译5,总结1,关于go-admingithu...
- 【开源】一款高效优雅的 Vite+Vue3 中后台管理模板——Arco-Admin
-
今天给大家分享一款开源的基于Vite、TypeScript和Vue3的中后台前端框架,结合了ArcoDesign提供的优雅设计与强大功能。值得一提的是,ArcoDesign是字节跳...
- 看看这样的Dotnet后台管理,那真是叫一个清新优雅高颜值!!!
-
MalusAdmin基于Vue3/TypeScript/NaiveUI和NET7&Sqlsugar开发的后台管理框架。采用最原生最简洁的方式来实现,前端清新优雅高颜值,后端结...
- NET 7 + Vue.js 的前后端分离的通用后台管理系统框架
-
DncZeus项目简介DncZeus是一个基于.NET7+Vue.js的前后端分离的通用后台管理系统框架。后端使用.NET7+EntityFrameworkCore构建,UI则...
- 后台管理系统这么受欢迎吗?又 Go 一个开源项目
-
大家好,我是欧盆索思(opensource),每天为你带来优秀的开源项目!之前推荐过两款后台管理系统,都是Go语言实现的。十分钟内构建数据可视化和管理后台:还同时支持众多框架基于Go语言Gi...
- 支持AI + 低代码!一款开箱即用的强大权限管理系统
-
写在前面大家好,这里是IT学习日记。今日推荐项目:cool-admin,获取方式在文后!1000+优质开源项目推荐进度:51/1000。如需更多类型优质项目推荐,请在文章后留言。项目简介如果你在为设计...
- 使用 Flask-Admin 快速开发博客后台管理系统:关键要点解析
-
一、为什么选择Flask-Admin?Flask-Admin是Flask生态中高效的后台管理框架,核心优势在于:-零代码生成CRUD界面:基于数据库模型自动生成增删改查功能-高度可定制...
- 通用后台管理系统需求及原型设计(后台管理系统需求分析)
-
编辑导读:后台管理系统,会根据不同公司、不同业务的要求做出改变。那么,有没有通用的功能和和需求设计模版呢?有的。本文作者基于自身工作经验,总结了一套通用的后台管理系统需求及原型设计,与你分享。网上很多...
- 基于 Vue3 后台管理平台Vue3.x-Admin
-
今天给大家分享一个Vue3.0框架搭建的后台管理模板Vue3.xAdmin。vue3.x-admin使用vue3开发的后台管理系统。主要包括CSS3特效、可拖拽的div、图表、益智小游戏、vuex4...
- 火爆全网:后台管理系统源码分享(项目部署+前后端手册+运维)
-
这是一款基于SpringBoot2.1.0、Jpa、SpringSecurity、redis、Vue的前后端分离的后台管理系统,项目采用分模块开发方式,权限控制采用RBAC,支持数...
- 好多程序员都在用的通用管理后台—likeadmin
-
前言作为一个程序员,最害怕的就是每次开新项目时,总是要从用户、角色、菜单、接口等一系列功能从头开始写代码,重复的工作实在是太多了,即耗费时间,又耗费精力,这个时候就需要一些能提高效率的工具,例如一个通...
- Axure无限级导航菜单(axure导航栏左右滑动怎么做)
-
在Axure设计中,树组件是展示层级结构数据的关键UI组件,广泛应用于文件管理、导航菜单和数据分类等场景。本篇文章将详细解析如何在Axure中构建一个实用的无限级导航菜单,帮助你高效管理和...
- 三星调整HBM团队组织架构 押宝定制化HBM
-
【三星调整HBM团队组织架构押宝定制化HBM】《科创板日报》27日讯,消息称,三星电子DS(设备解决方案)部门负责人全永铉正在进行内部组织大幅调整。他将三星HBM开发团队细分为标准HBM、定制化HB...
- 北森组织架构一览(北森总部地址)
-
北森的职级组织架构和职级名称都很有意思。可以作为企业参考。1)培养路径:森小白(BeisenNewcomer):新入职员工。森小贤(BeisenSage):L1层级森大侠(BeisenWarri...
- 高手正在使用的四个PLC编程思路,吃透让你少走20年弯路
-
在工业自动化领域,PLC(可编程逻辑控制器)编程是核心技能之一。掌握高效的编程思路不仅能提升工作效率,还能减少调试过程中的错误。以下是四条经过PLC工程师实践检验的编程思路,理解并运用这些思路可以让你...
你 发表评论:
欢迎- 一周热门
- 最近发表
-
- go-admin开源项目,快速搭建一个管理后台系统,直接二次开发上线
- 【开源】一款高效优雅的 Vite+Vue3 中后台管理模板——Arco-Admin
- 看看这样的Dotnet后台管理,那真是叫一个清新优雅高颜值!!!
- NET 7 + Vue.js 的前后端分离的通用后台管理系统框架
- 后台管理系统这么受欢迎吗?又 Go 一个开源项目
- 支持AI + 低代码!一款开箱即用的强大权限管理系统
- 使用 Flask-Admin 快速开发博客后台管理系统:关键要点解析
- 通用后台管理系统需求及原型设计(后台管理系统需求分析)
- 基于 Vue3 后台管理平台Vue3.x-Admin
- 火爆全网:后台管理系统源码分享(项目部署+前后端手册+运维)
- 标签列表
-
- MVC框架 (46)
- spring框架 (46)
- 框架图 (58)
- flask框架 (53)
- quartz框架 (51)
- abp框架 (47)
- jpa框架 (47)
- laravel框架 (46)
- springmvc框架 (49)
- 分布式事务框架 (65)
- scrapy框架 (56)
- shiro框架 (61)
- 定时任务框架 (56)
- java日志框架 (61)
- JAVA集合框架 (47)
- grpc框架 (55)
- ppt框架 (48)
- 内联框架 (52)
- winform框架 (46)
- gui框架 (44)
- cad怎么画框架 (58)
- ps怎么画框架 (47)
- ssm框架实现登录注册 (49)
- oracle字符串长度 (48)
- oracle提交事务 (47)