当前位置: 首页 > 工具软件 > FastAPI > 使用案例 >

FastAPI的介绍,特性,及几个常用案例

锺离马鲁
2023-12-01

一. 介绍

FastAPI 是一个用于构建 API 的现代、快速(高性能)的 web 框架,使用 Python 3.6+ 并基于标准的 Python 类型提示。

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

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

源码: https://github.com/tiangolo/fastapi

FastAPI依赖于下面这两大重要的成果:

  1. web部分参考:Starlette
  2. 数据部分参考:Pydantic

fastapi安装

  1. 安装fastapi: pip install fastapi
  2. 如果用于生产,那么你还需要一个ASGI服务器,如Uvicorn或Hypercorn: pip install uvicorn

可选的依赖

  1. Pydantic提供:
    ujson - 更快的JSON
    email_validator - 电子邮件的验证
  2. Starlette提供:
    requests - 如果你想要使用TestClient, 需要导入requests.
    aiofiles - 如果你想使用FileResponseor StaticFiles, 需要导入aiofiles.
    jinja2 - 如果你想使用默认的模板配置,需要导入jinjia2.
    python-multipart -如果要使用request.form()支持表单“解析”,则为必需。
    itsdangerous -“SessionMiddleware”支持需要。
    pyyaml - 如果需要 SchemaGenerator 支持, 则为必要.
    graphene -如果需要 GraphQLApp 支持, 则为必要.
    ujson - 如果你想使用 UJSONResponse, 则为必要.
  3. FastAPI / Starlette提供:
    uvicorn - 加载和提供应用程序的服务器.
  4. 一次性全部安装
    pip3 install fastapi[all]

根据官方介绍,我们看到FastAPI的速度得益于使用了Starlette——一个轻量级的ASGI框架。

ASGI,全称为Asynchronous Server Gateway Interface,为了规范支持异步的Python Web服务器、框架和应用之间的通信而定制,同时囊括了同步和异步应用的通信规范,并且向后兼容WSGI。由于最新的HTTP协议支持异步长连接,而传统的WSGI应用支持单次同步调用,即仅在接受一个请求后返回响应,从而无法支持HTTP长轮询或WebSocket连接。在Python3.5增加async/await特性之后,基于asyncio和协程的异步应用编程变得更加方便。ASGI协议规范就是用于asyncio框架的最低限度的底层服务器/应用程序接口。

异步非阻塞I/O & 协程

阻塞I/O,非阻塞I/O,I/O多路复用都属于同步I/O。而异步I/O则不一样,当进程发起I/O操作之后,就直接返回再也不理睬了,直到kernel发送一个信号,告诉进程说I/O完成。在这整个过程中,进程完全没有被阻塞。在非阻塞I/O中,虽然进程大部分时间都不会被阻塞,但是它仍然要求进程去主动的查询,并且当数据准备完成以后,也需要进程主动的再次调用recvfrom()来将数据拷贝到用户内存。

相对于线程,协程是程序级的I/O调度,是对一个线程进行分片,使得线程在代码块之间来回切换执行,而非逐行执行,因此能够支持更快的上下文切换。协程本身并不能实现高并发,但与I/O切换结合后能够大大提高性能。每当发生I/O,自动切换协程,让出CPU资源,即可减少高并发场景下服务的响应时间。因此,结合async/await语法,将代码块定义为协程,使用异步服务器即可实现程序级I/O切换和协程调度。

二. 关键特性:

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

三. 几个常用案例

3.1 第一个案例

# -*- encoding: utf-8 -*-
"""
@Author: cuiyonghua
@CreateDate: 2020/08/30 10:27 上午
@File: 第一个案例.py
@Description: 
"""
from typing import Optional

from fastapi import FastAPI

app = FastAPI()


@app.get("/")
def read_root():
    return {"message": "Hello World"}


@app.get("/items/{item_id}")
def read_item(item_id: int, q: Optional[str] = None):
    return {"item_id": item_id, "q": q}


if __name__ == '__main__':
    import uvicorn
    uvicorn.run(app, host="127.0.0.1", port=8000)

3.1.2 使用浏览器访问: http://127.0.0.1:8000/items/5?q=somequery

将会看到如下 JSON 响应:

{"item_id": 5, "q": "somequery"}
3.1.3 你已经创建了一个具有以下功能的 API:
通过 路径 / 和 /items/{item_id} 接受 HTTP 请求。
以上 路径 都接受 GET 操作(也被称为 HTTP 方法)。
/items/{item_id} 路径 有一个 路径参数 item_id 并且应该为 int 类型。
/items/{item_id} 路径 有一个可选的 str 类型的 查询参数 q。
3.1.4 交互式 API 文档

现在访问 http://127.0.0.1:8000/docs

你会看到自动生成的交互式 API 文档(由 Swagger UI生成):

升级版API文档可访问:http://127.0.0.1:8000/redoc

3.2 自定义响应状态码

# -*- encoding: utf-8 -*-
"""
@Author: cuiyonghua
@CreateDate: 2020/08/30 10:11 上午
@File: 自定义响应状态码.py
@Description: 
"""
from fastapi import FastAPI
from starlette import status

app = FastAPI()


# 201
@app.get("/201/", status_code=status.HTTP_201_CREATED)
async def item201():
    return {"httpStatus": 201}


# 302
@app.get("/302/", status_code=status.HTTP_302_FOUND)
async def items302():
    return {"httpStatus": 302, "message": '请求被禁止'}


# 404
@app.get("/404/", status_code=status.HTTP_404_NOT_FOUND)
async def items404():
    return {"httpStatus": 404}


# 500
@app.get("/500/", status_code=status.HTTP_500_INTERNAL_SERVER_ERROR)
async def items500():
    return {"httpStatus": 500}


if __name__ == '__main__':
    import uvicorn
    uvicorn.run(app, host="127.0.0.1", port=8000)

3.3 中间件_计算回调时间

# -*- encoding: utf-8 -*-
"""
@Author: cuiyonghua
@CreateDate: 2020/08/30 10:01 上午
@File: 中间件_计算回调时间.py
@Description: 
"""
import time
from fastapi import FastAPI
from starlette.requests import Request

app = FastAPI()


@app.middleware("http")
async def add_process_time_header(request: Request, call_next):
    start_time = time.time()
    response = await call_next(request)
    process_time = time.time() - start_time
    response.headers["X-Process-Time"] = str(process_time)
    print(response.headers)
    return response


@app.get("/")
async def main():
    return {"message": "Hello World"}


if __name__ == '__main__':
    import uvicorn
    uvicorn.run(app, host="127.0.0.1", port=8000)

四. 总结

  1. 总的来说,你就像声明函数的参数类型一样只声明了一次请求参数、请求体等的类型。

  2. 你使用了标准的现代 Python 类型来完成声明

    1. 用于创建 API 的 OpenAPI 包含了路径操作,请求参数,请求体,安全性等的声明。
    2. 使用 JSON Schema (因为 OpenAPI 本身就是基于 JSON Schema 的)自动生成数据模型文档。
    3. 经过了缜密的研究后围绕这些标准而设计。并非狗尾续貂。
    4. 这也允许了在很多语言中自动生成客户端代码。
  3. 你不需要去学习新的语法、了解特定库的方法或类,等等。

  4. 只需要使用标准的 Python 3.6 及更高版本。(全部都基于标准的 Python 3.6 类型声明(感谢 Pydantic )。没有新的语法需要学习。只需要标准的 Python 。)

  5. 安全性及身份验证:集成了安全性和身份认证。杜绝数据库或者数据模型的渗透风险。
    OpenAPI 中定义的安全模式,包括:

    1. HTTP 基本认证。
    2. OAuth2 (也使用 JWT tokens)。在 OAuth2 with JWT查看教程。
    3. API 密钥,在:请求头。查询参数。Cookies, 等等。
    4. 加上来自 Starlette(包括 session cookie)的所有安全特性。

    所有的这些都是可复用的工具和组件,可以轻松与你的系统,数据仓库,关系型以及 NoSQL 数据库等等集成。

 类似资料: