您当前的位置:首页 > 电脑百科 > 程序开发 > 框架

FastAPI - 一款新型的 Python Web 框架(对比 Flask)

时间:2021-12-23 11:29:44  来源:  作者:Python阿杰

近日只是为了想尽办法为 Flask 实现 Swagger UI 文档功能,基本上要让 Flask 配合 Flasgger, 所以写了篇 Flask 应用集成 Swagger UI 。然而不断的 google 过程中偶然间发现了 FastAPI 这么一款集成了 Swagger UI 的更新的 Python/ target=_blank class=infotextkey>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 的对比

  1. Flask 对返回的 dict 类型会自动应用 jsonify(), 并且响应的 Content-Type 为 application/json; 如果返回的是字符串,响应 Content-Type 为 text/html, 除非显式的调用 jsonify() 函数。FastAPI 都会生成 application/json 的响应,Flask 对返回的 tuple 类型还有更多的约定, 见 Flask About Response
  2. Flask 对路径中的参数可选择中 @app.xxx 装饰器中声明类型,如 app.get("/items/<int:item_id>"
  3. Flask 访问查询参数用 request.args.get('key') 的方式
  4. 启动服务的方式不同,下面单独列出

回顾一个 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 即刻映入眼帘

FastAPI - 一款新型的 Python Web 框架(对比 Flask)

 

同时注意到函数映射为 API 的名称,由于参数是带有类型提示的,所以在 SwaggerUI 中也能看到相应的类型。其他定制 Swagger UI 的工作需要时可细细研究。

FastAPI 除了 SwaggerUI 外,还同时给了我们另一个选择,那就是 redoc, 访问
http://localhost:8000/redoc, 看到下面的界面

FastAPI - 一款新型的 Python Web 框架(对比 Flask)

 

我也是头一回从 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} 的界面如下

FastAPI - 一款新型的 Python Web 框架(对比 Flask)

 

我们能看到请求与响应中的 Example Value 和 Schema 定义

梳理完 FastAPI 的自动 API 文档功能,进入下一个话题

FastAPI 的多文件支持

FastAPI 类似于 Flask 的 Blueprints 功能没有一个特定的名称,只笼统的给出解决方案 Bigger Applications - Multiple Files . 我们来看一下它是怎么实现的。这里简化官方的例子,排除了 dependencies 的应用,要用到的目录结构为

app
├── internal
│   └── admin.py
├── main.py
└── routers
    ├── items.py
    └── users.py

app

├── 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 分类) 的方式

  1. user.router: 在每个 API 中定义完整 API 路径(如 /users 为 URL 前缀) 以及 tags
  2. item.router: 声明 APIRouter 时统一指定 URL 前缀和 tags
  3. admin.router: 注册 APIrouter 到 app(FastAPI) 时指定 URL 前缀和 tags

现在运行

 $ uvicorn app.main:app --reload 

查看 SwaggerUI
http://localhost:8000/docs

FastAPI - 一款新型的 Python Web 框架(对比 Flask)

 

到目前为止我重点关注 FastAPI 的就是以上那两个特性:自动 API 文档与大程序多文件(Blueprint) 功能。其他的特性可查阅 FastAPI 的 Features 。比如:

  1. 自动的 JSON 反序列化
  2. 数据校验功能
  3. HTTP Basic, OAuth2, API keys 的支持
  4. WebSocket, 进程内后台任务,启动/关闭事件,CORS, GZIP, 静态文件,流响应数据,Session/Cookie
  5. 轻松与 GraphQL 集成

原文
https://yanbin.blog/fastapi-new-python-web-framework-vs-flask/



Tags:FastAPI   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
在本文中,我们将探讨如何为生产准备机器学习模型,并将其部署在简单的 Web 应用程序中。部署机器学习模型本身就是一门艺术。事实上,将机器学习模型成功投入生产超出了数据科学...【详细内容】
2022-03-25  Tags: FastAPI  点击:(85)  评论:(0)  加入收藏
近日只是为了想尽办法为 Flask 实现 Swagger UI 文档功能,基本上要让 Flask 配合 Flasgger, 所以写了篇 Flask 应用集成 Swagger UI 。然而不断的 Google 过程中偶然间发现了...【详细内容】
2021-12-23  Tags: FastAPI  点击:(384)  评论:(0)  加入收藏
FastAPI 是一个用于构建 API 的现代、快速(高性能)的 web 框架,使用 Python 3.6+ 并基于标准的 Python 类型提示。关键特性: 快速:可与 NodeJS 和 Go 比肩的极高性能(归功于 Star...【详细内容】
2021-05-10  Tags: FastAPI  点击:(717)  评论:(0)  加入收藏
▌简易百科推荐
本篇文章主要介绍了使用MyBatis框架完成数据库的增、删、改、查操作。准备工作运行schema.sql和data.sql脚本文件中的 SQL 语句创建t_user表并添加部分测试数据。schema.sql...【详细内容】
2022-07-15  嗨皮汪小成    Tags:MyBatis   点击:(0)  评论:(0)  加入收藏
1 Hive基本概念Hive是一个构建在Hadoop上的数据仓库框架。最初,Hive是由Facebook开发,后来移交由Apache软件基金会开发,并作为一个Apache开源项目。Hive是基于Hadoop的一个数据...【详细内容】
2022-07-15  秃头Java人    Tags:Hive   点击:(2)  评论:(0)  加入收藏
今天给大家讲讲 SpringBoot 框架 整合 Elasticsearch 实现海量级数据搜索。一、简介在上篇ElasticSearch 文章中,我们详细的介绍了 ElasticSearch 的各种 api 使用。实际的项...【详细内容】
2022-07-15  java小悠    Tags: Elasticsearch   点击:(3)  评论:(0)  加入收藏
SpringBoot开发Restful接口,有什么API规范吗?如何快速生成API文档呢?Swagger 是一个用于生成、描述和调用 RESTful 接口的 Web 服务。通俗的来讲,Swagger 就是将项目中所有(想要...【详细内容】
2022-07-14  Java全栈知识体系    Tags:Swagger   点击:(2)  评论:(0)  加入收藏
一、部署准备安装数据库、jdk、nginx、域名证书1、下载 nginx,官方网址如下:http://nginx.org/en/download.html2、解压安装包到任意目录 如:G:\nginx二、前端部署1、打开前端...【详细内容】
2022-07-14  智慧魔法豆浆    Tags:vue   点击:(2)  评论:(0)  加入收藏
SpringBoot 内置支持的 Web 容器有 Tomcat、Undertow、Jetty 和 Netty。默认情况下,这些 Web 服务的 AccessLog 日志是不开启的,而 AccessLog 日志对于做接口统计尤为重要。如...【详细内容】
2022-07-13  BUG弄潮儿    Tags:AccessLog 日志   点击:(10)  评论:(0)  加入收藏
什么是Starterstarter 是springboot 的核心,每个starter负责实现特定的功能,使用者只需引入starter即可自动配置,无需关心框架整合带来的问题。Starter 项目结构src |- main...【详细内容】
2022-07-12  IT食者    Tags:SpringBoot   点击:(9)  评论:(0)  加入收藏
mybaits非必填项处理数据库表字段khzjyxqx为日期型,非必填, 前台页面如下: 后台mybaits处理如下: 如果不处理,当为空时khzjyxqx=&#39;&#39;时会报错。<update id="updatesave" pa...【详细内容】
2022-07-11  在水一方357159258    Tags:mybaits   点击:(10)  评论:(0)  加入收藏
关于过气网红编程语言 Ruby,我们此前曾发过一篇文章去回顾其大受追捧的过往,并讨论了它每况愈下的生存状态。不过人气并不能直接说明语言质量差,一方面 Ruby on Rails(用 Ruby...【详细内容】
2022-07-08  InfoQ    Tags: Web 框架   点击:(9)  评论:(0)  加入收藏
1、JWT的构成- 头部(header):描述该JWT的最基本的信息,如类型以及签名所用的算法。- 负载(payload):存放有效信息的地方。- 签证(signature):base64加密后的header、base64加...【详细内容】
2022-07-08  dream19    Tags:SpringBoot   点击:(10)  评论:(0)  加入收藏
站内最新
站内热门
站内头条