首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

【Python框架】FastAPI快速上手

  • 25-04-18 13:21
  • 3788
  • 13308
juejin.cn

FastAPI

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

关键特性:

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

依赖¶

Python 及更高版本

FastAPI 站在以下巨人的肩膀之上:

  • Starlette 负责 web 部分。
  • Pydantic 负责数据部分。

安装¶

shell
代码解读
复制代码
pip install fastapi

你还会需要一个 ASGI 服务器,生产环境可以使用 Uvicorn 或者 Hypercorn。

shell
代码解读
复制代码
pip install "uvicorn[standard]"

示例¶

创建¶

  • 创建一个 main.py 文件并写入以下内容:
python
代码解读
复制代码
from typing import Union 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: Union[str, None] = None): return {"item_id": item_id, "q": q}

或者使用 async def...

如果你的代码里会出现 async / await,请使用 async def:

python
代码解读
复制代码
from typing import Union from fastapi import FastAPI app = FastAPI() @app.get("/") async def read_root(): return {"Hello": "World"} @app.get("/items/{item_id}") async def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q}

Note:

如果你不知道是否会用到,可以查看文档的  "In a hurry?"  章节中 关于 async 和 await 的部分。

运行¶

通过以下命令运行服务器:

vbnet
代码解读
复制代码
uvicorn main:app --reload INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit) INFO: Started reloader process [28720] INFO: Started server process [28722] INFO: Waiting for application startup. INFO: Application startup complete.

关于 uvicorn main:app --reload 命令......

uvicorn main:app 命令含义如下:

  • main:main.py 文件(一个 Python "模块")。
  • app:在 main.py 文件中通过 app = FastAPI() 创建的对象。
  • --reload:让服务器在更新代码后重新启动。仅在开发时使用该选项。

检查¶

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

你将会看到如下 JSON 响应:

json
代码解读
复制代码
{"item_id": 5, "q": "somequery"}

你已经创建了一个具有以下功能的 API:

  • 通过 路径 / 和 /items/{item_id} 接受 HTTP 请求。
  • 以上 路径 都接受 GET 操作(也被称为 HTTP 方法)。
  • /items/{item_id} 路径 有一个 路径参数 item_id 并且应该为 int 类型。
  • /items/{item_id} 路径 有一个可选的 str 类型的 查询参数 q。

交互式 API 文档¶

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

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

Swagger UI

可选的 API 文档¶

访问 http://127.0.0.1:8000/redoc。

你会看到另一个自动生成的文档(由 ReDoc 生成):

ReDoc

示例升级¶

现在修改 main.py 文件来从 PUT 请求中接收请求体。

我们借助 Pydantic 来使用标准的 Python 类型声明请求体。

python
代码解读
复制代码
from typing import Union from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() class Item(BaseModel): name: str price: float is_offer: Union[bool, None] = None @app.get("/") def read_root(): return {"Hello": "World"} @app.get("/items/{item_id}") def read_item(item_id: int, q: Union[str, None] = None): return {"item_id": item_id, "q": q} @app.put("/items/{item_id}") def update_item(item_id: int, item: Item): return {"item_name": item.name, "item_id": item_id}

服务器将会自动重载(因为在上面的步骤中你向 uvicorn 命令添加了 --reload 选项)。

交互式 API 文档升级¶

访问 http://127.0.0.1:8000/docs。

  • 交互式 API 文档将会自动更新,并加入新的请求体:

Swagger UI

  • 点击「Try it out」按钮,之后你可以填写参数并直接调用 API:

Swagger UI interaction

  • 然后点击「Execute」按钮,用户界面将会和 API 进行通信,发送参数,获取结果并在屏幕上展示:

Swagger UI interaction

可选文档升级¶

访问 http://127.0.0.1:8000/redoc。

  • 可选文档同样会体现新加入的请求参数和请求体:

ReDoc

总结¶

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

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

你不需要去学习新的语法、了解特定库的方法或类,等等。

只需要使用标准的 Python 及更高版本。

举个例子,比如声明 int 类型:

arduino
代码解读
复制代码
item_id: int

或者一个更复杂的 Item 模型:

makefile
代码解读
复制代码
item: Item

......在进行一次声明之后,你将获得:

  • 编辑器支持,包括:

    • 自动补全
    • 类型检查
  • 数据校验:

    • 在校验失败时自动生成清晰的错误信息
    • 对多层嵌套的 JSON 对象依然执行校验
  • 转换 来自网络请求的输入数据为 Python 数据类型。包括以下数据:

    • JSON
    • 路径参数
    • 查询参数
    • Cookies
    • 请求头
    • 表单
    • 文件
  • 转换 输出的数据:转换 Python 数据类型为供网络传输的 JSON 数据:

    • 转换 Python 基础类型 (str、 int、 float、 bool、 list 等)
    • datetime 对象
    • UUID 对象
    • 数据库模型
    • ......以及更多其他类型
  • 自动生成的交互式 API 文档,包括两种可选的用户界面:

    • Swagger UI
    • ReDoc

回到前面的代码示例,FastAPI 将会:

  • 校验 GET 和 PUT 请求的路径中是否含有 item_id。

  • 校验 GET 和 PUT 请求中的 item_id 是否为 int 类型。

    • 如果不是,客户端将会收到清晰有用的错误信息。
  • 检查 GET 请求中是否有命名为 q 的可选查询参数(比如 http://127.0.0.1:8000/items/foo?q=somequery)。

    • 因为 q 被声明为 = None,所以它是可选的。
    • 如果没有 None 它将会是必需的 (如 PUT 例子中的请求体)。
  • 对于访问 /items/{item_id} 的 PUT 请求,将请求体读取为 JSON 并:

    • 检查是否有必需属性 name 并且值为 str 类型 。
    • 检查是否有必需属性 price 并且值为 float 类型。
    • 检查是否有可选属性 is_offer, 如果有的话值应该为 bool 类型。
    • 以上过程对于多层嵌套的 JSON 对象同样也会执行
  • 自动对 JSON 进行转换或转换成 JSON。

  • 通过 OpenAPI 文档来记录所有内容,可被用于:

    • 交互式文档系统
    • 许多编程语言的客户端代码自动生成系统
  • 直接提供 2 种交互式文档 web 界面。


虽然我们才刚刚开始,但其实你已经了解了这一切是如何工作的。

尝试更改下面这行代码:

kotlin
代码解读
复制代码
return {"item_name": item.name, "item_id": item_id}

......从:

erlang
代码解读
复制代码
... "item_name": item.name ...

......改为:

erlang
代码解读
复制代码
... "item_price": item.price ...

......注意观察编辑器是如何自动补全属性并且还知道它们的类型:

editor support


Python 类型提示简介¶

Python 3.6+ 版本加入了对"类型提示"的支持。

这些 "类型提示" 是一种新的语法(在 Python 3.6 版本加入)用来声明一个变量的类型。

通过声明变量的类型,编辑器和一些工具能给你提供更好的支持。

这只是一个关于 Python 类型提示的快速入门 / 复习。它仅涵盖与 FastAPI 一起使用所需的最少部分...实际上只有很少一点。

整个 FastAPI 都基于这些类型提示构建,它们带来了许多优点和好处。

但即使你不会用到 FastAPI,了解一下类型提示也会让你从中受益。

动机¶

让我们从一个简单的例子开始:

Python 3.8+

scss
代码解读
复制代码
def get_full_name(first_name, last_name): full_name = first_name.title() + " " + last_name.title() return full_name print(get_full_name("john", "doe"))

运行这段程序将输出:

代码解读
复制代码
John Doe

这个函数做了下面这些事情:

  • 接收 first_name 和 last_name 参数。
  • 通过 title() 将每个参数的第一个字母转换为大写形式。
  • 中间用一个空格来拼接它们。

Python 3.8+

diff
代码解读
复制代码
def get_full_name(first_name, last_name): + full_name = first_name.title() + " " + last_name.title() return full_name print(get_full_name("john", "doe"))

修改示例¶

这是一个非常简单的程序。

现在假设你将从头开始编写这段程序。

在某一时刻,你开始定义函数,并且准备好了参数...。

现在你需要调用一个"将第一个字母转换为大写形式的方法"。

等等,那个方法是什么来着?upper?还是 uppercase?first_uppercase?capitalize?

然后你尝试向程序员老手的朋友——编辑器自动补全寻求帮助。

输入函数的第一个参数 first_name,输入点号(.)然后敲下 Ctrl+Space 来触发代码补全。

但遗憾的是并没有起什么作用:

添加类型¶

让我们来修改上面例子的一行代码。

我们将把下面这段代码中的函数参数从:

markdown
代码解读
复制代码
first_name, last_name

改成:

python
代码解读
复制代码
first_name: str, last_name: str

就是这样。

这些就是"类型提示":

Python 3.8+

diff
代码解读
复制代码
+ def get_full_name(first_name: str, last_name: str): full_name = first_name.title() + " " + last_name.title() return full_name print(get_full_name("john", "doe"))

这和声明默认值是不同的,例如:

ini
代码解读
复制代码
first_name="john", last_name="doe"

这两者不一样。

我们用的是冒号(:),不是等号(=)。

而且添加类型提示一般不会改变原来的运行结果。

现在假设我们又一次正在创建这个函数,这次添加了类型提示。

在同样的地方,通过 Ctrl+Space 触发自动补全,你会发现:

这样,你可以滚动查看选项,直到你找到看起来眼熟的那个:

更多动机¶

下面是一个已经有类型提示的函数:

Python 3.8+

diff
代码解读
复制代码
+ def get_name_with_age(name: str, age: int): name_with_age = name + " is this old: " + age return name_with_age

因为编辑器已经知道了这些变量的类型,所以不仅能对代码进行补全,还能检查其中的错误:

现在你知道了必须先修复这个问题,通过 str(age) 把 age 转换成字符串:

Python 3.8+

diff
代码解读
复制代码
def get_name_with_age(name: str, age: int): + name_with_age = name + " is this old: " + str(age) return name_with_age


Starlette介绍

Starlette 是一个轻量级的 ASGI 框架/工具包, 非常适合在 Python 中构建异步 Web 服务。

它已准备好用于生产,并为您提供以下功能:

  • 一个轻量级、低复杂度的 HTTP Web 框架。
  • WebSocket 支持。
  • 进程内后台任务。
  • 启动和关闭事件。
  • 基于 构建的测试客户端。httpx
  • CORS、GZip、静态文件、流式响应。
  • 会话和 Cookie 支持。
  • 100% 的测试覆盖率。
  • 100% 类型注释的代码库。
  • 很少的硬依赖项。
  • 兼容 和 后端。asyncio``trio
  • 与独立基准测试相比,整体性能出色。

安装

代码解读
复制代码
pip install starlette

您还需要安装 ASGI 服务器,例如 uvicorn、daphne 或 hypercorn。

代码解读
复制代码
pip install uvicorn

例

main.py

python
代码解读
复制代码
from starlette.applications import Starlette from starlette.responses import JSONResponse from starlette.routing import Route async def homepage(request): return JSONResponse({'hello': 'world'}) app = Starlette(debug=True, routes=[ Route('/', homepage), ])

然后运行应用程序...

css
代码解读
复制代码
uvicorn main:app

参考链接

  • 一文读懂WSGI和ASGI_wsgi asgi-CSDN博客
注:本文转载自juejin.cn的lnix的文章"https://juejin.cn/post/7478185513461268480"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

103
后端
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2024 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top