FastAPI一款新型的PythonWeb框架(对比Flask)
近日只是为了想尽办法为 Flask 实现 Swagger UI 文档功能,基本上要让 Flask 配合 Flasgger, 所以写了篇 Flask 应用集成 Swagger UI 。然而不断的 Google 过程中偶然间发现了 FastAPI 这么一款集成了 Swagger UI 的更新的 Python Web 框架。起初想要在标题中表达的意思大概是 Flask + Swagger = FastAPI, 后来发现 FastAPI 的闪亮点不仅如此,顺便找了些 Flask 与 FastAPI 对比的文章来,在文后附有链接。
本文不对 Flask 与 FastAPI 的各个方面对进行对比,本人兴趣依然还在 FastAPI 的 Swagger UI 功能,以及与 Flask 的 Blueprint 类似的特性。如果要拿 Flask 与 FastAPI 比较的话,应该用 Flask 2.x, 因为它开始支持类似 @app.get 的装饰器,并引入了 async 路由函数。
Flask 是在 2010 年发布的,它构建于 WSGI(Python Web Server Gateway Interface) 之上的,产品环境中运行需与 uWSGI, Gunicorn 搭配,或用 mod_wsgi 模块与 Apache 集成。因发布较早,所以目前应该有较多的使用者。Flask 2.0 需要 Python 3.6+ 的支持,如果支持 async , 需 Python 3.7+
FastAPI 发布于 2018 年,构建于 ASGI(Asynchronous Server Gateway Interface) 之上,在 IO 密集型的应用中有更优越的性能。生成环境中配合 ASGI 服务器,如 Uvicorn 或 Hypercorn . FastAPI 最为亮丽的特性是集成了 Swagger UI -- 外加一个福利 ReDoc 。FastAPI 需 Python 3.6+ 版本。
毕竟是在开始学一个新的框架,还是从它的基本用法开始,途中会穿插与 Flask 的对比。 FastAPI 的基本用法
安装: $ pip install fastapi $ pip install "uvicorn[standard]"
当前安装的 fastapi 版本为 0.70.1, uvicorn 版本为 0.16.0。开始第一个例子,摘自官方
创建一个 main.py 文件,内容为 from typing import Optional from fastapi import FastAPI app = FastAPI() @app.get("/") def read_root(): return {"Hello": "World"} @app.get("/items/{item_id}") def read_item(item_id: int, q: Optional[str] = None): return {"item_id": item_id, "q": q}from typing import Optional
from fastapi import FastAPI
app = FastAPI ( )
@ app . get ( "/" )
def read_root ( ) :
return { "Hello" : "World" }
@ app . get ( "/items/{item_id}" )
def read_item ( item_id : int , q : Optional [ str ] = None ) :
return { "item_id" : item_id , "q" : q }
注:以上两个函数前面可以加上 async 关键字
启动服务,用命令 $ uvicorn main:app --reload INFO: Will watch for changes in these directories: ["/Users/yanbin/demo/first-fastapi"] INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) INFO: Started reloader process [81730] using watchgod INFO: Started server process [81732] INFO: Waiting for application startup. INFO: Application startup complete.
注: uvicorn --help 列出详细帮助,如启动多少个 worker, 绑定网络接口和端口号, 配置 SSL 证书等。
访问服务 $ curl -i http://localhost:8000/ HTTP/1.1 200 OK date: Mon, 20 Dec 2021 06:51:24 GMT server: uvicorn content-length: 17 content-type: application/json {"Hello":"World"}
另一个服务就是 http://localhost:8000/items/100?q=somequery
与 Flask 的对比 Flask 对返回的 dict 类型会自动应用 jsonify(), 并且响应的 Content-Type 为 application/json; 如果返回的是字符串,响应 Content-Type 为 text/html, 除非显式的调用 jsonify() 函数。FastAPI 都会生成 application/json 的响应,Flask 对返回的 tuple 类型还有更多的约定, 见 Flask About Response Flask 对路径中的参数可选择中 @app.xxx 装饰器中声明类型,如 app.get("/items/" Flask 访问查询参数用 request.args.get("key") 的方式 启动服务的方式不同,下面单独列出
回顾一个 Flask 启动服务的方式有 $ export FLASK_APP=hello $ flask run
如果程序文件名为 app.py 或 wsgi.py 的话,可以省略 FLASK_APP 环境变量,直接执行 flask run 就行。另一种方式就是在代码中加上 main 入口 if __name__ == "__main__": app.run()if __name__ == "__main__" :
app . run ( )
然后像普通 Python 代码一样执行 $ python main.py
对于 FastAPI, 如果总是要用 uvicorn 来启动服务的话,在 IDE 中调用就变得不那么便利。由于 uvicorn 本身就是 Python 实现,当然也就可以把命令过程写到 Python 代码中 from fastapi import FastAPI import uvicorn app = FastAPI() if __name__ == "__main__": uvicorn.run(app)from fastapi import FastAPI
import uvicorn
app = FastAPI ( )
if __name__ == "__main__" :
uvicorn . run ( app )
注:uvicorn.run() 可接受更多的参数,相当于 uvicorn --help 可接受的。
同样把 main.py 当作普通 Python 程序来启动即可 $ python main.py FastAPI 自动产生的 Web 文档
前面讲过,FastAPI 进入我的视野最首要的一个原因就是它集成了 Swagger UI, 在启动了 FastAPI 服务后,只要访问 http://localhost:8000/docs, 熟悉的 Swagger UI 即刻映入眼帘
同时注意到函数映射为 API 的名称,由于参数是带有类型提示的,所以在 SwaggerUI 中也能看到相应的类型。其他定制 Swagger UI 的工作需要时可细细研究。
FastAPI 除了 SwaggerUI 外,还同时给了我们另一个选择,那就是 redoc, 访问 http://localhost:8000/redoc, 看到下面的界面
我也是头一回从 FastAPI 这里了解到还有一个 Redoc 的 Web API 文档工具,它和 SwaggerUI 类似,都是支持 Open API。 API Spec 中包含请求/响应的 Model
使用 FastAPI 时,在 API 文档中产生请求/响应的 Model 类型也很简单,下面的例子同时包含自定义的输入输出类型
下面是 main.py 的全新内容 from typing import Optional from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() class Item(BaseModel): name: str price: float is_offer: Optional[bool] = None class Msg(BaseModel): item_id: int item_name: str @app.put("/items/{item_id}", response_model=Msg) def update_item(item_id: int, item: Item): return {"item_name": item.name, "item_id": item_id}from typing import Optional
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI ( )
class Item ( BaseModel ) :
name : str
price : float
is_offer : Optional [ bool ] = None
class Msg ( BaseModel ) :
item_id : int
item_name : str
@ app . put ( "/items/{item_id}" , response_model = Msg )
def update_item ( item_id : int , item : Item ) :
return { "item_name" : item . name , "item_id" : item_id }
再查看 http://localhost:8000/docs 文档,看到 PUT /items/{item_id} 的界面如下
我们能看到请求与响应中的 Example Value 和 Schema 定义
梳理完 FastAPI 的自动 API 文档功能,进入下一个话题 FastAPI 的多文件支持
FastAPI 类似于 Flask 的 Blueprints 功能没有一个特定的名称,只笼统的给出解决方案 Bigger Applications - Multiple Files . 我们来看一下它是怎么实现的。这里简化官方的例子,排除了 dependencies 的应用,要用到的目录结构为 app internal admin.py main.py routers items.py users.pyapp
internal
admin . py
main . py
routers
items . py
users . py
每个目录中都可以放一个 __init__.py 文件,标识为包,接着是每个文件的内容
app/internal/admin.py from fastapi import APIRouter router = APIRouter() @router.get("/") def admin(): return "admin"from fastapi import APIRouter
router = APIRouter ( )
@ router . get ( "/" )
def admin ( ) :
return "admin"
app/routers/items.py from fastapi import APIRouter router = APIRouter(prefix="/items", tags=["tag_items"]) @router.get("/") async def read_items(): return {"__all__"} @router.delete("/{item_id}") def delete_item(item_id: int): return {"action": "delete", "item_id": item_id}from fastapi import APIRouter
router = APIRouter ( prefix = "/items" , tags = [ "tag_items" ] )
@ router . get ( "/" )
async def read_items ( ) :
return { "__all__" }
@ router . delete ( "/{item_id}" )
def delete_item ( item_id : int ) :
return { "action" : "delete" , "item_id" : item_id }
app/routers/users.py from fastapi import APIRouter router = APIRouter() @router.get("/users/{username}", tags=["users"]) def read_user(username: str): return {"username": username} @router.post("/users/{username}", tags=["users"]) async def add_user(username: str): return {"action": "add", "username": username, "userid": "new_id"}from fastapi import APIRouter
router = APIRouter ( )
@ router . get ( "/users/{username}" , tags = [ "users" ] )
def read_user ( username : str ) :
return { "username" : username }
@ router . post ( "/users/{username}" , tags = [ "users" ] )
async def add_user ( username : str ) :
return { "action" : "add" , "username" : username , "userid" : "new_id" }
在每个单独定义路由的文件里用到的是 APIRouter , 它相当是一个迷你的 FastAPI , 也类似于 Flask 的 Blueprint . 上面分别演示了两种 APIRouter 的声明方式,声明时带不带 prefix 和 tags。同时在为函数定义路由时也可指定 tags,在后面我们将会注意到 tags 只是为 API 文档分类用的。
app/main.py from fastapi import FastAPI from .internal import admin from .routers import users, items app = FastAPI() app.include_router(users.router) app.include_router(items.router) app.include_router(admin.router, prefix="/admin", tags=["admin"]) @app.get("/") def index(): return "index"from fastapi import FastAPI
from . internal import admin
from . routers import users , items
app = FastAPI ( )
app . include_router ( users . router )
app . include_router ( items . router )
app . include_router ( admin . router , prefix = "/admin" , tags = [ "admin" ] )
@ app . get ( "/" )
def index ( ) :
return "index"
这里实际上使用了三种定义路径前缀与 tags(API 分类) 的方式 user.router: 在每个 API 中定义完整 API 路径(如 /users 为 URL 前缀) 以及 tags item.router: 声明 APIRouter 时统一指定 URL 前缀和 tags admin.router: 注册 APIrouter 到 app(FastAPI) 时指定 URL 前缀和 tags
现在运行 $ uvicorn app.main:app --reload
查看 SwaggerUI http://localhost:8000/docs
到目前为止我重点关注 FastAPI 的就是以上那两个特性:自动 API 文档与大程序多文件(Blueprint) 功能。其他的特性可查阅 FastAPI 的 Features 。比如: 自动的 JSON 反序列化 数据校验功能 HTTP Basic, OAuth2, API keys 的支持 WebSocket, 进程内后台任务,启动/关闭事件,CORS, GZIP, 静态文件,流响应数据,Session/Cookie 轻松与 GraphQL 集成
原文 https://yanbin.blog/fastapi-new-python-web-framework-vs-flask/
工业自动化控制可以简单化吗?距离2021还剩40多天了,抓住2020的尾巴,触想智能宣布大家关注已久的第五代新品已经上线啦!细心的盆友会发现,此前在上海工博会华南工博会现场以及相关推文中,触想智能2020年全
制造生产智能硬件,普级中级高级配套应用是什么?在工业制造生产中,工序的多重性分工的繁杂性以及工业软件系统的多样性,使得许多工业应用更倾向于整套解决方案和配套设备。这就意味着通过这些解决方案和配套设备,解决的不止是用户某一个使用
医疗智能化之路,工业级智能自助终端发挥什么作用?信息时代的发展,让智能化成为现今人们生活方式不可缺少的一部分。从智能手机到各类智能电子产品,还有柜台服务逐步变成自助终端服务,再到普及全国的线上支付和智能物流等等,智能化体现在我们
如何优化与拓展停车场?智能停车给出答案智慧停车是智慧城市中的一部分。现代化城市管理展现出的复杂与实时性,都需要城市管理者变革旧有的管理思路,跟上城市发展需要,显得更加智能高效便民。城市车辆的快速增加,不仅带来交通拥堵问
嵌入式一体机在城市智能终端中的应用,助力智能城市化智能自助终端设备一般由人机界面组成,由用户根据设备提示引导进行操作,主要特点体现在自助上。智能自助终端的出现是社会向数字化和智能化发展的表现,一方面,它大大方便了人们的生活,可以在
什么是机房巡检AI机器人?工业平板电脑的应用如何体现机房巡检AI机器人,顾名思义,它的主要工作是在机房里做巡逻检查,是巡检机器人类别下的一个型号,类似的还有电站巡检AI机器人,铁路巡检AI机器人等,总之,它们的设计研发就是为了某个特
CNC加工机床,在工业平板电脑中有两种可能?CNC加工作为现代生产制造中工重要流程之一,这类新型加工技术,主要通过机械编程设置加工路线,就可实现自动化高精度高效率的器件加工,因此得以广泛应用于各类自动化生产车间制造工厂。比如
把政务搬进互联网,透明高效,规范便捷数字化政务是新的时代背景下提出的概念,在物联网云计算信息通讯等技术发展到一定阶段,通过运用新技术与政务的融合,在政务管理上呈现出的新形态。依据社会发展的潮流和应对新的管理诉求,各级
分级诊疗如何推进?远程医疗一体化会诊车来支招医疗是一个国家的重要板块,医疗质量关乎国计民生,中国人口众多,医疗资源大都集中在经济发达地区和各省会城市,人们看病也普遍认为就应该去大医院,这会形成了一个问题,大医院人满为患,小医
自动焊接机中的PLC技术如何应用实现?伴随工业数字化自动化智能化的发展,机械控制技术得到飞速发展,行业对自动焊接需求的不断增加,让其在各工业的应用中所发挥的作用越来越大,应用范围正在迅速扩大。应用背景作为建立在电动机控
与一般材料加工相比,超硬材料加工有何不一样?超硬材料加工作为工业制造重要产业之一,主要用途在于制造加工成其它材料的工具,尤其是在加工硬质材料用具方面,具有无可比拟的优越性和不可替代性。(网络用图侵删)超硬材料一般分为天然钻石