自学内容网 自学内容网

Python 之 Fastapi 框架学习

依赖安装

Fastapi 有版本要求,需要的 Python 版本至少是 Python 3.8(不要犟,按照版本要求来,我最先也是在我 Python3.6 上装的,果不其然跑不起来),幸好我 Win7 老古董能支持的 Python 最高版本可以到 3.8 ,这也算我最后的倔强了。据说这个框架有和 Go 并肩的极高性能,我倒是想特别见识一下。

大家也可以直接去看用户指南 教程 - 用户指南 - FastAPI ,这里面讲解得更加详细。

安装 fastapi

这个用 pip 安装就是了,没啥多说的,特别是安装有多个 python 解释器的时候,要关注下 pip 和 python 解释器的对应关系。当然,用虚拟环境也是不错的选择。

pip3.8 install fastapi

安装ASGI 服务器

pip3.8 install "uvicorn[standard]"

这点和 flask 不太一样,flask 创建的 app 直接用 app.run() 就跑起来了,它好像不能这么做,需要使用安装的 uvicorn 去启动服务。

Uvicorn是一个基于ASGI(Asynchronous Server Gateway Interface)的异步Web服务器,用于运行异步Python web应用程序。它是由编写FastAPI框架的开发者设计的,旨在提供高性能和低延迟的Web服务。

快速启动

hello world

import uvicorn
from fastapi import FastAPI

app = FastAPI()


@app.get("/")
async def index():
    """
    注册一个根路径
    :return:
    """
    return {"message": "Hello World"}


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

文档访问

SwaggerUi风格文档:http://127.0.0.1:8000/docs

有了路由的在线文档,对于接口对接或者 API 接口文档编写的时候,就真正方便多了。

OpenAPI

FastAPI框架内部实现了OpenAPI 规范,通过访问 http://127.0.0.1:8000/openapi.json,我们可以看到整个项目的 API对应的JSON描述。简单来说,这就是一个结构化的 Swagger 文档,返回的细节很详细。

{
  "openapi": "3.1.0",
  "info": {
    "title": "FastAPI",
    "version": "0.1.0"
  },
  "paths": {
    "/": {
      "get": {
        "summary": "Index",
        "description": "注册一个根路径\n:return:",
        "operationId": "index__get",
        "responses": {
          "200": {
            "description": "Successful Response",
            "content": {
              "application/json": {
                "schema": {}
              }
            }
          }
        }
      }
    }
  }
}

路径

路径参数

类似于 Flask 的动态路由,使用 Python 标准类型注解(自从有了类型注解以后,总感觉 Python 变了,不像是原来那个不关心类型的脚步语言了),声明路径操作函数中路径参数的类型。

import uvicorn
from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
def read_item(item_id: int):
    return {"item_id": item_id}


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

如果输入的参数类型不匹配的话,还会报错。

{
  "detail": [
    {
      "type": "int_parsing",
      "loc": [
        "path",
        "item_id"
      ],
      "msg": "Input should be a valid integer, unable to parse string as an integer",
      "input": "xyz",
      "url": "https://errors.pydantic.dev/2.6/v/int_parsing"
    }
  ]
}

路径顺序

import uvicorn
from fastapi import FastAPI

app = FastAPI()


@app.get("/users/me")
async def read_user_me():
    return {"user_id": "the current user"}


@app.get("/users/{user_id}")
async def read_user(user_id: str):
    return {"user_id": user_id}


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

比如要使用 /users/me 获取当前用户的数据。然后还要使用 /users/{user_id},通过用户 ID 获取指定用户的数据。由于路径操作是按顺序依次运行的,因此,一定要在 /users/{user_id} 之前声明 /users/me 。这个其实好理解,相当于先写的动态路由把后面的其他路由通配了。一般如果代码审查比较严格的话,是不允许出现这种情况的。特殊的路由就用特殊的路径,尽量不要和通配路径去碰瓷。

路径预设值

路径操作使用 Python 的 Enum 类型接收预设的路径参数也就是说和动态路由类似,但是动态值的可选范文是提前限定好的。

import uvicorn
from enum import Enum

from fastapi import FastAPI


class ModelName(Enum):
    alexnet = "alexnet"
    resnet = "resnet"
    lenet = "lenet"


app = FastAPI()


@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
    if model_name is ModelName.alexnet:
        return {"model_name": model_name, "message": "Deep Learning FTW!"}

    if model_name.value == "lenet":
        return {"model_name": model_name, "message": "LeCNN all the images"}

    return {"model_name": model_name, "message": "Have some residuals"}


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

查询参数

查询参数都是 URL 的组成部分,因此,它们的类型本应是字符串。但声明 Python 类型之后,这些值就会转换为声明的类型,并进行类型校验。

import uvicorn
from fastapi import FastAPI

app = FastAPI()

fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]


@app.get("/items/")
async def read_item(skip: int = 0, limit: int = 10):
    return fake_items_db[skip: skip + limit]


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

默认值

即在声明类型的时候,按照上面的示例指定默认值即可。

可选参数

将参数的默认值设置为 None 之后,就可以将参数变为可选参数。

import uvicorn
from fastapi import FastAPI

app = FastAPI()

fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]


@app.get("/items/{item_id}")
async def read_item(item_id: str, query: str = None):
    if query:
        return {"item_id": item_id, "query": query}
    return {"item_id": item_id}


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

内容估计有些多,先写一部分,后面再补充。

To be continued


原文地址:https://blog.csdn.net/TomorrowAndTuture/article/details/137329833

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!