用它5分钟以后,我放弃用了四年的 Flask
有一个非常简单的需求:编写一个 HTTP接口,使用 POST 方式发送一个 JSON 字符串,接口里面读取发送上来的参数,对其中某个参数进行处理,并返回。
如果我们使用 Flask 来开发这个接口,那么代码是这样的:
from flask import Flask, request
app = Flask(__name__)
@app.route('/insert', methods=['POST'])
def insert():
    info = request.json
    name = info['name']
    age = info['age']
    age_after_10_years = age + 10
    msg = f'此人名叫:{name},10年后,此人年龄:{age_after_10_years}'
    return {'success': True, 'msg': msg}
复制代码
代码看起来已经很简洁了。我们用requests发个请求看看效果,如下图所示:
看起来没什么问题。
现在,我搞点破坏,把age字段改成字符串,再运行一下:
不出所料,报错了。
现在我们把age字段改回数字,但是直接移除name字段:
又报错了。
为了防止用户不按规矩提交数据,我们必需在接口里面做好各种异常数据的判断。于是增加判断以后的代码变得复杂了:
@app.route('/insert', methods=['POST'])
def insert():
    info = request.json
    name = info.get('name', '')
    if not name:
        return {'success': False, 'msg': 'name 参数不可省略,不可为空!'}
    age = info.get('age', 0)
    if not isinstance(age, int):
        return {'success': False, 'msg': 'age参数不是数字!'}
    age_after_10_years = age + 10
    msg = f'此人名叫:{name},10年后,此人年龄:{age_after_10_years}'
    return {'success': True, 'msg': msg}
复制代码
看来,用 Flask,虽然能让你用很短的代码写出一个能工作的项目。但要写成一个可以正常使用的项目,还是需要你自己写更多代码。
下面我们来看一下,现代化的 web 框架:FaskApi能把这个工程简化到什么程度:
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class People(BaseModel):
    name: str
    age: int
    address: str
    salary: float
@app.post('/insert')
def insert(people: People):
    age_after_10_years = people.age + 10
    msg = f'此人名字叫做:{people.name},十年后此人年龄:{age_after_10_years}'
    return {'success': True, 'msg': msg}
复制代码
我们还是使用 requests 发一条信息给 FastApi 开发的 HTTP接口。对于正常数据,正常使用:
现在我们把age字段改成字符串:
返回友好的提示信息,告诉我类型错误:age 字段不是 integer。
我们再试一试把name字段去掉:
返回友好信息,提示值错误:name字段丢失。
整个过程中,对类型的检查全都由 FastApi 自己完成。我们省下来很多时间。
我用了 Flask 四年,但在使用了5分钟 FastApi 以后,我决定以后不再使用 Flask 了。
回过头来,我们好好介绍一下 FastApi。
使用pip或者pipenv即可安装 FastApi:
pip install fastapi
pipenv install fastapi
复制代码
安装完成以后,我们来完成第一个 API:
from fastapi import FastAPI
app = FastAPI()
@app.get('/')
def index():
    return {'message': '你已经正确创建 FastApi 服务!'}
复制代码
这里的写法跟 Flask 几乎一致。只不过在 Flask 中,我们定义路由的装饰器为@app.route('/')。而这里写为@app.get('/')
如下图所示:
写好代码以后,我们需要使用uvicorn来运行 FastApi。首先使用pip或者pipenv安装uvicorn:
pip install uvicorn
pipenv install uvicorn
复制代码
然后执行命令:
uvicorn main:app --reload
复制代码
其中main表示我们的代码文件为main.py,app表示我们初始化的FastApi 对象的名字。--reload参数表示在修改了代码以后立即生效,不需要重启。
运行命令以后,我们访问http://127.0.0.1:8000可以看到接口已经正确返回了 JSON 格式的数据:
那么如何定义一个带参数的 GET 方法呢?我们再写一段代码:
@app.get('/query/{uid}')
def query(uid):
    msg = f'你查询的 uid 为:{uid}'
    return {'success': True, 'msg': msg}
复制代码
写好代码以后,我们直接在浏览器里面访问新的地址,可以看到修改已经生效了,如下图所示:
如果想限定uid 只能是数字,不能是字符串怎么办呢?你只需要多加4个字符:
@app.get('/query/{uid}')
def query(uid: int):
    msg = f'你查询的 uid 为:{uid}'
    return {'success': True, 'msg': msg}
复制代码
对函数query的参数使用类型标注,标注为 int 类型。现在我们再来访问一下接口:
当 query 后面的参数不是整数时,正常报错了。
我们再来看一下本文一开始的 POST 方法。在使用 Flask 的时候,我们需要手动验证用户 POST 提交上来的数据是什么格式的,字段对不对。
但使用 FastApi 的时候,我们只需要类型标注就能解决所有问题。首先我们导入from pydantic import BaseModel,然后继承BaseModel实现我们允许 POST 方法提交上来的数据字段和格式:
from pydantic import BaseModel
app = FastAPI()
class People(BaseModel):
    name: str
    age: int
    address: str
    salary: float
复制代码
People这个类通过类型标注,指定了它里面的4个字段和他们的类型。现在,我们来实现 POST 方法:
@app.post('/insert')
def insert(people: People):
    age_after_10_years = people.age + 10
    msg = f'此人名字叫做:{people.name},十年后此人年龄:{age_after_10_years}'
    return {'success': True, 'msg': msg}
复制代码
insert函数的参数people通过类型标注指定为People类型。
当我们使用 POST 方式提交数据时,FastApi 自动会以People中定义的字段为基准来校验数据,发现不对就返回报错信息。
除了开发接口变得非常简单外,FastApi 还会自动帮我们生成接口文档。大家访问http://127.0.0.1:8000/docs,可以看到接口文档已经自动生成好了:
这个接口不仅能看,而且直接就能在接口页面修改样例数据,发送请求,现场测试:
以上是对 FastApi 的极简介绍。有兴趣的同学可以查阅它的官方文档
最后,告诉大家,FastApi 是一个异步 Web 框架,它的速度非常非常非常快。远远超过 Flask。
FastApi 是最快的几个 Web 框架之一。速度可以匹敌 Golang写的接口。详细的对比可以看:one of the fastest Python frameworks available
文末福利
用它5分钟以后,我放弃用了四年的 Flask的更多相关文章
- Python爬虫从入门到放弃(十四)之 Scrapy框架中选择器的用法
		Scrapy提取数据有自己的一套机制,被称作选择器(selectors),通过特定的Xpath或者CSS表达式来选择HTML文件的某个部分Xpath是专门在XML文件中选择节点的语言,也可以用在HTM ... 
- 大白话5分钟带你走进人工智能-第四节最大似然推导mse损失函数(深度解析最小二乘来源)(2)
		第四节 最大似然推导mse损失函数(深度解析最小二乘来源)(2) 上一节我们说了极大似然的思想以及似然函数的意义,了解了要使模型最好的参数值就要使似然函数最大,同时损失函数(最小二乘)最小,留下了一 ... 
- 三分钟教你学Git(十四) 之 线下传输仓库
		有时候还有一个人不能从远程直接clone仓库或者说由于非常大,clone非常慢或其他原因.我们能够使用bundle命令将Git仓库打包,然后通过U盘或者是其他介质拷贝给他,这样他拿到打包好的仓库后能够 ... 
- 后端API入门到放弃指北
		后端API入门学习指北 了解一下一下概念. RESTful API标准] 所有的API都遵循[RESTful API标准]. 建议大家都简单了解一下HTTP协议和RESTful API相关资料. 阮一 ... 
- ElasticSearch入门系列(六)分布式操作
		一.路由文档到分片 当你索引一个文档的时候,他被存储在单独一个主分片上.Elasticsearch根据一个算法来找到所在分片上. shard=hash(routing)%number_of_prima ... 
- 2010  A  B    2011   A B
		湖南人文科技学院公共课 2010---2011学年第1学期<中国近代史纲要>课程考核试卷(A) 考核方式: (闭卷) ... 
- 2012  A                         《中国近现代史纲要》课程期末考试试卷
		湖南人文科技学院2012—2013学年第1学期公共课 2011级<中国近现代史纲要>课程期末考试试卷 考核方式:(开卷) ... 
- TCP/IP详解之:TCP
		第17章 TCP:传输控制协议 TCP提供了一种可靠的面向连接的字节流运输层服务 TCP的服务 尽管TCP和UDP都使用相同的网络层(IP),TCP却向应用层提供与UDP完全不同的服务. TCP通过下 ... 
- 艰苦的RAW格式数据恢复之旅
		艰苦的RAW格式数据恢复之旅 1.RAW 格式形成原因 2.RAW 格式的解决的方法 经验之谈: 1.RAW 格式形成原因 关于形成的原因,在网上搜索了下,千奇百怪的都有,就不一一诉说了,可是有果必有 ... 
随机推荐
- IDEA 2020.1 查看内存使用情况
- 使用recv函数和send函数的技巧
			一些述说 recv函数用于socket通信中接收消息,接口定义如下: int recv(SOCKET s, char *buf, int len, int flags) 参数一:指定接收端套接字描述符 ... 
- springMVC(二)springMVC、Mybatis、spring整合
			数据库设置: 一.配置文件设置 (1).springMVC配置文件(前端控制器web.xml,核心配置文件springmvc.xml) <?xml version="1.0" ... 
- 网页批量打印成PDF,并按条件合并成大PDF、生成页码
			题记:因为老板要求将过去一年内系统中的订单合同内容进行打印,并按月进行整理成纸质文件.合同在系统(web系统)中以html形式显示,打印单份都是在网页中右键打印,订单量上千份,每笔订单有两份合同,如果 ... 
- java实现链表反转
			为什么面试常考链表反转 链表是常用的数据结构,同时也是面试常考点,链表为什么常考,因为链表手写时,大多都会有许多坑,比如在添加节点时因为顺序不对的话会让引用指向自己,因此会导致内存泄漏等问题,Java ... 
- 4. JSON字符串是如何被解析的?JsonParser了解一下
			公司不是你家,领导不是你妈.本文已被 https://www.yourbatman.cn 收录,里面一并有Spring技术栈.MyBatis.JVM.中间件等小而美的专栏供以免费学习.关注公众号[BA ... 
- excel文件双击打开空白
			excel文件双击打开之后进入软件,没有去读文件 一.现象描述 打开现象如下所示,只有excel模板,看不到excel中的表格模板. 二.想要打开文件 (1)在软件的文件--->打开--> ... 
- PHP array_pad() 函数
			实例 返回 5 个元素,并将 "blue" 值插入到数组的新元素中: <?php$a=array("red","green");pri ... 
- Python time tzset()方法
			描述 Python time tzset() 根据环境变量TZ重新初始化时间相关设置.高佣联盟 www.cgewang.com 标准TZ环境变量格式: std offset [dst [offset ... 
- PHP imagechar - 写出横向字符
			imagechar — 写出横向的字符.高佣联盟 www.cgewang.com 语法 bool imagechar ( resource $image , int $font , int $x , ... 
