用官方的话来说,FastAPI 是一种现代,快速(高性能)的 Web 框架,基于标准Python 类型提示使用 Python 3.6 构建 api

tornadopython框架(简析一个比Flask和Tornado更高性能的API)(1)

FastAPI 站在巨人的肩膀上?

很大程度上来说,这个巨人就是指 Flask 框架。

FastAPI 从语法上和 Flask 非常的相似,有异曲同工之妙。

技术背景:Py3.6 ,Starlette,Pydantic

其实不仅仅是 FastAPI ,就连 Sanic 也是基于 Flask 快速开发的 Web API 框架。

废话少说,代码总是能给人带来愉悦感 (抱头),直接开怼。

安装

pipinstallfastapi pipinstalluvicorn

创建一个 main.py 文件

fromfastapiimportFastAPI app=FastAPI()#创建api对象 @app.get("/")#根路由 defroot(): return{"武汉":"加油!!!"} @app.get("/say/{data}") defsay(data:str,q:int): return{"data":data,"item":q}

上面搭建了一个最简单的 FastAPI 应用,看起来和 Flask 完全一样,莫名的喜感。

使用以下命令来启动服务器:

uvicornmain:app--reload

FastAPI 推荐使用 uvicorn 来运行服务,Uvicorn 是基于uvloop 和 httptools 构建的闪电般快速的 ASGI 服务器。

uvicorn main:app 指的是:

main:文件main.py

app: 创建的启用对象

--reload: 热启动,方便代码的开发

启动界面如下:

tornadopython框架(简析一个比Flask和Tornado更高性能的API)(2)

INFO 信息告诉我们已经监听了本地的 8000 端口,访问 http://127.0.0.1:8000 得到结果

tornadopython框架(简析一个比Flask和Tornado更高性能的API)(3)

传入参数

tornadopython框架(简析一个比Flask和Tornado更高性能的API)(4)

再来看看 FastAPI 的异步代码

fromfastapiimportFastAPI app=FastAPI()#创建api对象 @app.get("/")#根路由 asyncdefroot(): return{"武汉":"加油!!!"} @app.get("/say/{data}") asyncdefsay(data:str,q:int=None): return{"data":data,"q":q}

开启服务后访问结果是一样的。

在上面的路由方法中,我们传入了一个 q 参数并且初始为 None,如果不给默认值,并且不传参,代码将直接报错。

来看看 FastAPI 是如何处理错误的:

tornadopython框架(简析一个比Flask和Tornado更高性能的API)(5)

可以看到,即使是报错,也是优美的输入一个带有错误字段的 JSON,这就非常的友好了,这也是体现了 FastAPI 减少更多的人为错误的特性,返回也更加的简洁直观。

在命令行输出:

tornadopython框架(简析一个比Flask和Tornado更高性能的API)(6)

再来看看 FastAPI 的交互文档

根据官方文档,打开 http://127.0.0.1:8000/docs

看到:

tornadopython框架(简析一个比Flask和Tornado更高性能的API)(7)

支持动态传入数据:

tornadopython框架(简析一个比Flask和Tornado更高性能的API)(8)

结果:

tornadopython框架(简析一个比Flask和Tornado更高性能的API)(9)

从交互体验上也是无比的友好,让代码在生产中更加健壮。

现在我们算是快速的体验了一波 FastAPI 骚操作,从代码上和 Flask 及其的类似,体验性更好。

那么再来看看最新的 Python web框架的性能响应排行版

tornadopython框架(简析一个比Flask和Tornado更高性能的API)(10)

从并发性上来说是完全碾压了 Flask (实际上也领先了同为异步框架的tornado 不少),看来 FastAPI 也真不是盖的,名副其实的高性能 API 框架呀!

查询参数

先来看看官方小 demo

fromfastapiimportFastAPI app=FastAPI() fake_items_db=[{"item_name":"Foo"},{"item_name":"Bar"},{"item_name":"Baz"}] @app.get("/items/") asyncdefread_item(skip:int=0,limit:int=10): returnfake_items_db[skip:skip limit]

该查询是 ? URL中位于关键字之后的一组键值对,以&字符分隔。

在 url 中进行查询

http://127.0.0.1:8000/items/?skip=0&limit=10

skip:查询的起始参数

limit:查询的结束参数

tornadopython框架(简析一个比Flask和Tornado更高性能的API)(11)

成功返回查询列表。

查询参数类型转换

FastAPI 非常聪明,足以辨别 路径参数 和 查询参数。

来看看具体的例子:

fromfastapiimportFastAPI app=FastAPI() @app.get("/items/{item_id}") asyncdefread_item(item_id:str,q:str=None,short:bool=False): item={"item_id":item_id} ifq: item.update({"q":q}) ifnotshort: item.update( {"description":"Thisisanamazingitemthathasalongdescription"} ) returnitem

看看其访问路径,执行以下的任何一种 url 访问方式

http://127.0.0.1:8000/items/武汉加油?short=1

http://127.0.0.1:8000/items/武汉加油?short=True

http://127.0.0.1:8000/items/武汉加油?short=true

http://127.0.0.1:8000/items/武汉加油?short=on

http://127.0.0.1:8000/items/武汉加油?short=yes

可以发现任何大小写的字母等都会被转换成 bool 值的参数 True,这就是所谓模糊验证参数,对于开发者来说这是个好消息。

要知道的是,如果 short 参数没有默认值,则必须传参,否则 FastAPI 将会返回类似以下的错误信息。

{ "detail":[ { "loc":[ "query", "needy" ], "msg":"fieldrequired", "type":"value_error.missing" } ] }

创建数据模型

前面说到 FastAPI 依赖 Pydantic 模块,所以首先,你需要导入 Pydantic 的 BaseModel 类。

fromfastapiimportFastAPI frompydanticimportBaseModel # 请求主体类 classItem(BaseModel): name: str = "武汉加油 !!" description:str=None price:float = 233 tax:float=None app=FastAPI() @app.post("/items/") asyncdefcreate_item(item:Item): returnitem

发送 post 请求来提交一个 Item(请求主体) 并返回,来看看提交过程。

tornadopython框架(简析一个比Flask和Tornado更高性能的API)(12)

成功提交并返回 200 状态码

请求主体 路径 查询参数,在请求主体的基础上加入 url 动态路径参数 和 查询参数

fromfastapiimportFastAPI frompydanticimportBaseModel classItem(BaseModel): name:str description:str=None price:float tax:float=None app=FastAPI() @app.put("/items/{item_id}") asyncdefcreate_item(item_id:int,item:Item,q:str=None): result={"item_id":item_id,**item.dict()} ifq: result.update({"q":q}) returnresult

put 方法用于更新,传入参数后成功返回一个字典。

关于模板引擎

FastAPI 不像 Flask 那样自带 模板引擎(Jinja2),也就是说没有默认的模板引擎,从另一个角度上说,FastAPI 在模板引擎的选择上变得更加灵活,极度舒适。

以 Jinja2 模板为例

安装依赖

pipinstalljinja2 pipinstallaiofiles # 用于 fastapi 的异步静态文件

具体的用法

#-*-coding:utf-8-*- fromfastapiimportFastAPI,request fromfastapi.staticfilesimportStaticFiles fromfastapi.templatingimportJinja2Templates importuvicorn app=FastAPI() app.mount("/static",StaticFiles(directory="static"),name="static")#挂载静态文件,指定目录 templates=Jinja2Templates(directory="templates")#模板目录 @app.get("/data/{data}") asyncdefread_data(request:Request,data:str): returntemplates.TemplateResponse("index.html",{"request":request,"data":data}) if__name__=='__main__': uvicorn.run(app,host="127.0.0.1",port=8000)

html 文件渲染

<html> <head> <title>武汉加油</title> </head> <body> <h1>高呼:{{data}}</h1> </body> </html>

在浏览器键入 http://127.0.0.1:8000/data/武汉加油

tornadopython框架(简析一个比Flask和Tornado更高性能的API)(13)

值得注意的是,在返回的 TemplateRespone 响应时,必须带上 request 的上下文对象,传入参数放在同一字典。

这样一来,又可以像 Flask 一样的使用熟悉的 Jinja2 了,哈哈。

做个小总结的话就是 FastAPI 在用法上也是及其简单,速度更快,性能更好,容错率更高,整体上更牛逼。但是我在设想如此之快的框架,毕竟发布的时间不长,缺少像 Flask 框架的第三方库和各种插件,所以要想真正意义上替代还是需要一定的时间,要冷静,冷静。

好啊,至此 FastAPI 的一些基本用法就差不多结束啦,FastAPI 的官方文档有详细的介绍和实例,入门篇到此结束。

官方文档:https://fastapi.tiangolo.com/

,