FastAPI 快速学习之 Flask 框架对比

目录

    • 一、前言
    • 二、FastAPI 优势
    • 三、Hello World
    • 四、HTTP 方法
    • 五、URL 变量
    • 六、查询字符串
    • 七、POST 请求
    • 八、文件上传
    • 九、表单提交
    • 十、Cookies
    • 十一、模块化视图
    • 十二、数据校验
    • 十三、自动化文档
      • Swagger 风格
      • ReDoc 风格
    • 十四、CORS跨域

一、前言

       本文主要对 FastAPI 与 Flask 框架进行对比,以助快速学习。进一步了解FastAPI的高级使用方法,可参考FastAPI官方文档。如果对你有帮助,欢迎三连 收藏点赞关注!!!
 
       Flask作为Python语言中的老牌Web框架,已经被应用于大量的Python Web开发项目,其使用简洁,支持工具众多,工具丰富,社区活跃,是Python Web框架中的佼佼者之一。而近来,FastAPI的出众表现,已使得其越来越受到众多开发者的关注,成为Web开发主流框架之一。

---- NickYoung


二、FastAPI 优势

  • 高效运行:可与 NodeJS 和 Go 并肩的极高性能(归功于 Starlette 和 Pydantic)。史称最快的 Python web 框架之一。
  • 高效编码:提高功能开发速度约 200% 至 300%。
  • 更少 bug:减少约 40% 的人为(开发者)导致错误。
  • 直观易用:支持强大的编辑器功能、自动补全和更少的调试时间。
  • 简单易学:设计的易于使用和学习,阅读文档的时间更短。
  • 降低冗余:使代码重复最小化。通过不同的参数声明实现丰富功能。
  • 健壮可靠:生产可用级别的代码。还有自动生成的交互式文档。
  • 标准化:基于(并完全兼容)API 的相关开放标准:OpenAPI (以前被称为 Swagger) 和 JSON Schema。

下面将会结合Flask的使用作为对比,来介绍FastAPI,作为FastAPI的入门教程。
本文使用的两个Web框架版本如下:

fastapi==0.101.1
Flask==2.3.3

三、Hello World

  • Flask 代码
from flask import Flask

app = Flask(__name__)

@app.route('/')
def home():
    return 'hello world'

if __name__ == '__main__':
    app.run()
  • FastAPI 代码
import uvicorn
from fastapi import FastAPI

app = FastAPI()


@app.get('/')
def home():
    return 'hello world'


if __name__ == '__main__':
    uvicorn.run(app)

两者的代码差别不多,运行时Flask的默认端口为5000,FastAPI的端口为8000,使用curl命令请求(FastAPI),返回结果如下:

$ curl localhost:8000/
"hello world"

在部署生产代码时,Flask使用gunicorn,示例命令如下:
gunicorn app:app
而FastAPI使用uvicorn,示例命令如下:
uvicorn app:app
当然,在实际部署时还可指定端口(port)、worker数量、最大连接数等,本文不再详述。

四、HTTP 方法

常见的HTTP请求方法有GET, POST, PUT, PATCH, DELETE等。
以POST方法为例

  • Flask 代码
@app.route('/', methods=['POST'])
def example():
    ...
  • FastAPI 代码
@app.post('/')
def example():
    ...

其它HTTP请求方法的使用方法如下:

@app.get('/')
@app.put('/')
@app.patch('/')
@app.delete('/')

五、URL 变量

我们想从URL中获取user id,比如/users/1,然后将user id返回给用户。

  • Flask 代码
@app.route('/users/<int:user_id>')
def get_user_details(user_id):
    return {'user_id': user_id}
  • FastAPI 代码
@app.get('/users/{user_id}')
def get_user_details(user_id: int):
    return {'user_id': user_id}

使用curl命令模拟请求如下:

$ curl localhost:8000/users/2
{"user_id":2}

六、查询字符串

我们希望允许用户在URL中使用查询字符串 ?q=abc 来指定搜索词。

  • Flask 代码
from flask import request

@app.route('/search')
def search():
    query = request.args.get('q')
    return {'query': query}
  • FastAPI 代码
@app.get('/search')
def search(q: str):
    return {'query': q}

使用curl命令模拟请求如下:

$ curl 'localhost:8000/search?q=abcde'
{"query":"abcde"}

如果要指定多个搜索词,可以&符号隔开,比如:?name=Jack&id=1

七、POST 请求

我们希望发送一个带有text参数JSON POST请求,返回其小写形式。

# Request
{"text": "HELLO"}

# Response
{"text": "hello"}
  • Flask 代码
from flask import request

@app.route('/lowercase', methods=['POST'])
def lower_case():
    text = request.json.get('text')
    return {'text': text.lower()}
  • FastAPI 代码
from typing import Dict

@app.post('/lowercase')
def lower_case(json_data: Dict):
    text = json_data.get('text')
    return {'text': text.lower()}

注意:FastAPI还有更优雅的处理方式,那就是引入Pydantic schema,它可以将JSON格式数据映射为schema对象,同时对该对象中的数据类型进行校验,如校验不通过,则会返回自动生成的校验错误。

  • FastAPI 更优雅的代码
class Sentence(BaseModel):
    text: str

@app.post('/lowercase')
def lower_case(sentence: Sentence):
    return {'text': sentence.text.lower()}

使用curl命令模拟请求如下:

$ curl --location 'localhost:8000/lowercase' \
--header 'Content-Type: application/json' \
--data '{
"text": "HELLO"
}'
{"text":"hello"}

在请求时,如果text对应的value为数字时,FastAPI会自动将数字转化为字符串,不会报错;如果text对应的value为null时,FastAPI将会报错,信息如下:

{
  "detail": [
    {
      "loc": [
        "body",
        "text"
      ],
      "msg": "none is not an allowed value",
      "type": "type_error.none.not_allowed"
    }
  ]
}

八、文件上传

我们来创建一个上传文件的API,返回上传文件的文件名。

  • Flask 代码
from flask import Flask, request

app = Flask(__name__)

@app.route('/upload', methods=['POST'])
def upload_file():
    file = request.files.get('file')
    return {'name': file.filename}
  • FastAPI 代码
from fastapi import FastAPI, UploadFile, File

app = FastAPI()

@app.post('/upload')
def upload_file(file: UploadFile = File(...)):
    return {'name': file.filename}

使用Postman模拟请求如下:

$ curl --location 'localhost:8000/upload' \
--header 'Content-Type: multipart/form-data' \
--form 'file=@"/Users/admin/Documents/test.pdf"'
{"name": "test.pdf"}

九、表单提交

我们希望从表单中获取text类型的变量,并返回它的值,如下:

  • Flask 代码
from flask import Flask, request

app = Flask(__name__)

@app.route('/submit', methods=['POST'])
def echo():
    city = request.form.get('city')
    return {'city': city}
  • FastAPI 代码
from fastapi import FastAPI, Form

app = FastAPI()

@app.post('/submit')
def echo(city: str = Form(...)):
    return {'city': city}

使用curl命令模拟请求如下:

$ curl --location 'localhost:8000/submit' \
--form 'city="shanghai"'
{"city":"shanghai"}

十、Cookies

我们希望从请求的cookie中获取name字段的值。

  • Flask 代码
from flask import Flask, request

app = Flask(__name__)

@app.route('/profile')
def profile():
    name = request.cookies.get('name')
    return {'name': name}
  • FastAPI 代码
from fastapi import FastAPI, Cookie

app = FastAPI()

@app.get('/profile')
def profile(name=Cookie(None)):
    return {'name': name}

十一、模块化视图

我们希望将单个的app.py文件分解成视图(多个独立的文件),如下:

- app.py
- views
  - user.py
  • Flask 代码

在Flask中,我们可以使用蓝图(Blueprint)来管理,代码如下:

from flask import Blueprint

user_blueprint = Blueprint('user', __name__)

@user_blueprint.route('/users')
def list_users():
    return {'users': ['a', 'b', 'c']}
from flask import Flask

from views.user import user_blueprint

app = Flask(__name__)
app.register_blueprint(user_blueprint)
  • FastAPI 代码

在FastAPI中,与蓝图等价的实现形式为router,首先需创建一个user router如下:

from fastapi import APIRouter

router = APIRouter()

@router.get('/users')
def list_users():
    return {'users': ['a', 'b', 'c']}
# app.py
from fastapi import FastAPI
from routers import user

app = FastAPI()
app.include_router(user.router)

十二、数据校验

Flask本身并没有提供数据校验功能,可使用marshmalllow或pydantic模块来辅助实现。
而FastAPI在其框架中已包装pydantic模块,可轻松实现数据校验。示例代码如下:

import uvicorn
from fastapi import FastAPI
from pydantic import BaseModel

app = FastAPI()


class User(BaseModel):
    name: str
    age: int


@app.post('/users')
def save_user(user: User):
    return {'name': user.name,
            'age': user.age}


if __name__ == '__main__':
    uvicorn.run(app)

关于pydantic的schema与JSON格式对应关系,在此给出三个例子:

  • 例子1 键值对(key-value pairs)
{
  "name": "Isaac",
  "age": 60
}
from pydantic import BaseModel

class User(BaseModel):
    name: str
    age: int
  • 例子2 列表
{
  "series": ["GOT", "Dark", "Mr. Robot"]
}
from pydantic import BaseModel
from typing import List

class Metadata(BaseModel):
    series: List[str]
  • 例子3 嵌套对象
{
  "users": [
    {
      "name": "xyz",
      "age": 25
    },
    {
      "name": "abc",
      "age": 30
    }
  ],
  "group": "Group A"
}
from pydantic import BaseModel
from typing import List

class User(BaseModel):
    name: str
    age: int

class UserGroup(BaseModel):
    users: List[User]
    group: str

十三、自动化文档

Flask并没有提供内置的自动化文档生成,可使用flask-swagger或flask-restful模块来辅助实现。
FastAPI可生成自动化文档,文档风格包括swagger和redoc,其中swagger对应路径为/docs,redoc对应路径为/redoc,如下所示:

Swagger 风格


ReDoc 风格

十四、CORS跨域

  • Flask本身不支持CORS,可使用flask-cors模块辅助实现,代码如下:
from flask import Flask
from flask_cors import CORS

app_ = Flask(__name__)
CORS(app_)
  • FastAPI提供了内置的中间件来处理CORS,示例代码如下:
# app.py
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=['*'],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/104888.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

驱动开发5 阻塞IO实例、IO多路复用

1 阻塞IO 进程1 #include <stdlib.h> #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <fcntl.h> #include <unistd.h> #include <string.h>int main(int argc, char co…

【2021集创赛】Arm杯三等奖:基于FPGA的人脸检测SoC设计

本作品参与极术社区组织的有奖征集|秀出你的集创赛作品风采,免费电子产品等你拿~活动。 团队介绍 参赛单位&#xff1a;合肥工业大学 队伍名称&#xff1a;芯创之家 指导老师&#xff1a;邓红辉、尹勇生 参赛杯赛&#xff1a;Arm杯 参赛人员&#xff1a;王亮 李嘉燊 金京 获奖情…

【WinForm详细教程一】WinForm中的窗体、Label、TextBox及Button控件、RadioButton和CheckBox、ListBox

文章目录 1.WinForm文件结构2. 窗体的常用属性、方法与事件2.1 常用属性&#xff08;可直接在属性中设置&#xff09;2.2 常用方法2.3 常用事件 3.Label、TextBox及Button控件4.RadioButton和CheckBox5.ListBox&#xff08;列表框&#xff09; 1.WinForm文件结构 .sln文件 &am…

Hadoop分布式安装

首先准备好三台服务器或者虚拟机&#xff0c;我本机安装了三个虚拟机&#xff0c;安装虚拟机的步骤参考我之前的一篇 virtualBox虚拟机安装多个主机访问虚拟机虚拟机访问外网配置-CSDN博客 jdk安装 参考文档&#xff1a;Linux 环境下安装JDK1.8并配置环境变量_linux安装jdk1.8并…

干货很干:5个有效引流方法,让客户找上门

如何才能把用户引流到私域&#xff1f;是很多老板&#xff0c;店主&#xff0c;线上创业者的卡点&#xff0c;今天分享5个实用方法&#xff1a; ✅线下导流 ✅巧用搜索 ✅同行互推 ✅社群引流 ✅内容输出 所以引流不仅需要知道方法&#xff0c;还需要知道底层逻辑&#xff0c;也…

uniapp开发微信小程序的巨坑

1、不能使用v-show 2、关于插槽的巨坑 这里我真的是摸索了好久。 小程序版本&#xff1a; hbuilderx版本&#xff1a; 其他版本不知道会不会出现以下情况。 如果组件中带有插槽&#xff0c;那么使用插槽时有以下要注意&#xff1a; 1、如果子组件通过slot&#xff0c;向外…

SQL sever中的函数(基础)

目录 一、聚合函数 1.1聚合函数概述 1.2SUM(求和)函数 1.3AVG(平均值)函数 1.4MIN(最小值)函数 1.5MAX(最大值)函数 1.6COUNT(统计)函数 1.6.1COUNT函数用法分类 1.6.2COUNT函数用法示例 1.7DISTINCT(取不重复记录)函数 1.8查询重复记录 二、数学函数 2.1数学函数…

ELK概述部署和Filebeat 分布式日志管理平台部署

ELK概述部署、Filebeat 分布式日志管理平台部署 一、ELK 简介二、ELK部署2.1、部署准备2.2、优化elasticsearch用户拥有的内存权限2.3、启动elasticsearch是否成功开启2.4、浏览器查看节点信息2.5、安装 Elasticsearch-head 插件2.6、ELK Logstash 部署&#xff08;在 Apache 节…

中国密码算法与NIST标准对比

1. 引言 NIST定义AES为标准的对称密钥加密算法。但NIST被指出可能在加密算法中添加NSA后门。为此&#xff0c;在中国&#xff0c;ShāngM (SM) 系列密码算法&#xff0c;作为TLS 1.3集成和无线认证的备选方案&#xff1a; SM2&#xff1a;定义了认证&#xff08;签名&#xf…

cuda卸载

去查看你的电脑显卡对应的cuda版本&#xff0c;不然还是一整个用不到gpu的情况嘿嘿. 啊啊啊啊打开控制面板看一下&#xff0c;驱动不要乱卸载&#xff1a; 这些东西不能全部卸载了哦&#xff0c;只能卸载含有“CUDA”的那几个&#xff08;其实其他的可能也没有用 但是不懂的哇 …

用Rust和cURL库做一个有趣的爬虫

以下是一个使用 Rust 和 cURL 库的下载器程序&#xff0c;用于从wechat下载音频。此程序使用了 [/get_proxy] 提供的代码。 extern crate curl;use std::io::{self, Read}; use std::process::exit; use curl::easy::Easy;fn main() {let url "https://www.wechat.com/au…

vue3 源码解析(1)— reactive 响应式实现

前言 本文是 vue3 源码解析系列的第一篇文章&#xff0c;项目代码的整体实现是参考了 v3.2.10 版本&#xff0c;项目整体架构可以参考之前我写过的文章 rollup 实现多模块打包。话不多说&#xff0c;让我们通过一个简单例子开始这个系列的文章。 举个例子 <!DOCTYPE html…

Web攻防05_MySQL_二次注入堆叠注入带外注入

文章目录 MYSQL-二次注入-74CMS思路描述&#xff1a;注入条件&#xff1a;案例&#xff1a;74CMS个人中心简历功能 MYSQL-堆叠注入-CTF强网思路描述注入条件案例&#xff1a;2019强网杯-随便注&#xff08;CTF题型&#xff09; MYSQL-带外注入-DNSLOG注入条件使用平台带外应用场…

Mybatis-Plus CRUD

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; Mybatis-Plus CRUD 通用 Service CRUD 封装 IService 接口&#xff0c;进一步封装 CRUD 采用 get 查询、remove 删除 、list 查询集合、page 分页的前缀命名方式区分 …

【0229】libpq库实现压测PG服务器max_connections的最大连接数

1. PG服务器接收的最大连接数 在PG服务的postgresql.conf配置文件中,参数:max_connections 注明了PG服务所能够接受的最大客户端的连接数量。此值默认是100,那么PG服务此参数最大能够调到多大呢? 本文将采用libpq库编写demo来进行压测,并将最终的结论和数据于文章中给出。…

UWB技术在定位系统中的革新应用

超宽带技术&#xff08;Ultra-Wideband, UWB&#xff09;的崛起为定位系统领域带来了前所未有的机遇。其亚米级别的高精度定位、强大的穿透能力以及高速数据传输的特性&#xff0c;使得UWB在室内和室外定位系统中得以广泛应用。本文将深入探讨UWB技术在定位系统中的应用&#x…

关于数据可视化那些事

干巴巴的数据没人看&#xff0c;数据可视化才能直观展现数据要点&#xff0c;提升数据分析、数字化运营决策效率。那关于可视化的实现方式、技巧、工具等&#xff0c;你了解几分&#xff1f;接下来&#xff0c;我们就来聊聊数据可视化那些事。 1、什么是数据可视化&#xff1f…

java 企业工程管理系统软件源码 自主研发 工程行业适用

工程项目管理软件&#xff08;工程项目管理系统&#xff09;对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营&#xff0c;全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&am…

LeetCode刷题---简单组(三)

文章目录 &#x1f352;题目一 20. 有效的括号&#x1f352;解法一&#x1f352;题目二 26. 删除有序数组中的重复项&#x1f352;解法一&#x1f352;题目三 21. 合并两个有序链表&#x1f352;解法一 &#x1f352;题目一 20. 有效的括号 给定一个只包括 ‘(’&#xff0c;‘…

在antd里面渲染MarkDown并且自定义一个锚点目录TOC(重点解决导航目录不跟随文档滚动的问题)

一、整体思路 由于有很多很长的文档需要渲染&#xff0c;我觉得用MarkDown的方式会比较适合管理&#xff0c;所以这两天测试了一下在antd里面集成MarkDown的渲染模块。 总体思路参考&#xff1a; https://blog.csdn.net/Sakuraaaa_/article/details/128400497 感恩大佬的倾情付…