快速API中如何使用Starlette和Pydantic


快速API是:

主要功能:

  • 快速:非常高的性能,可与NodeJS和Go媲美(感谢Starlette和Pydantic)。它是最快的Python框架之一。

....

FastAPI站在巨人的肩膀上。

  • Web部分是Starlette
  • 数据部分为Pydantic

它在文档中以

的形式演唱。

站在肩膀上是什么意思?我想知道如何使用它。
我们将在以下流程中介绍Starlette和Pydantic。

  • ASGI服务器
  • ASGI框架/工具包
  • 数据验证/序列化

ASGI服务器

首先,让我们看一下" ASGI",它是FastAPI与" Web"相关的功能之一。
ASGI服务器是指根据ASGI规范处理HTTP请求的服务器。

以下库对应于ASGI服务器。

  • 葡萄胎
  • 超级玉米
  • 这样

要获取该过程的图像,请比较以上两个ASGI服务器文档中的helloworld示例。

胎盘样本

Uvicorn --helloworld

uvicorn_example.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
async def app(scope, receive, send):
    assert scope['type'] == 'http'

    await send({
        'type': 'http.response.start',
        'status': 200,
        'headers': [
            [b'content-type', b'text/plain'],
        ],
    })
    await send({
        'type': 'http.response.body',
        'body': b'Hello, world!',
    })

服务器启动:

1
uvicorn uvicorn_example:app

如果使用

浏览器访问http://127.0.0.1:8000/,它将显示为Hello, world!

Hypercorn样本

Hypercorn --Helloworld

hypercorn_example.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
async def app(scope, receive, send):
    if scope["type"] != "http":
        raise Exception("Only the HTTP protocol is supported")

    await send({
        'type': 'http.response.start',
        'status': 200,
        'headers': [
            (b'content-type', b'text/plain'),
            (b'content-length', b'5'),
        ],
    })
    await send({
        'type': 'http.response.body',
        'body': b'hello',
    })

服务器启动:

1
hypercorn hypercorn_example:app

如果使用

浏览器访问http://127.0.0.1:8000/,它将显示为hello

ASGI服务器

的作用

与示例稍有不同,所需的函数参数及其用法完全相同(因为这不是巧合,因此遵循ASGI规范)。您可以在此示例中想象,ASGI服务器为:

  • 接收HTTP请求,将请求信息传递给异步功能,执行异步处理并返回响应
  • 该接口是通用的,与库无关
  • 将应用程序部分(如何响应请求)留给用户

它具有

的功能。

换句话说,通过使用ASGI服务器,您可以专注于实现充分利用以下三个功能的应用程序,而不必担心如何处理HTTP请求。

  • 作用域-包含传入连接信息的字典
  • receive-接收来自ASGI服务器的消息的通道
  • send-用于将发送消息发送到ASGI服务器的通道

另外,使用FastAPI时,循环处理不会出现在任何地方,但实际上,服务器会反复接收请求并返回响应。之所以这样建立,是因为Fast API定义了上述应用程序(app)函数,而ASGI服务器则循环调用了上述应用程序函数。

关于性能

Uvicorn和Hypercorn使用称为uvloop的库来执行异步处理。它在Cython中实现,似乎比内置asyncio event loop快2-4倍。 (参考)

FastAPI似乎很快,因为实现了uvloop的高速异步处理。

请注意,它更快,因为它通过异步处理(async)一起处理多个请求,因此,在比较单独返回一个请求的速度时,它并不总是更好的结果。

ASGI框架/工具包

ASGI服务器单独充当Web服务器,但是在一般的Web应用程序中使用它时,必须描述很多处理过程。

例如,

  • 路由
  • 错误处理
  • 中间件的添加
  • 这样

另外,当数据量很大时,即使是基本过程"接收请求/发送响应"也无法在单个通信中发送,因此有必要在应用程序内重复分割和发送/接收。这很麻烦。

使用ASGI Framework / toolkit是因为上面的通用处理可以很容易地使用。

Starlette

Starlette是搭载Fast API的巨头之一,是ASGI Framework /工具包之一。

具有以下功能。处理不仅容易,而且已经设计出异步处理来有效地执行它,并且速度很快。

它已准备就绪,可以为您提供以下内容:

  • 令人印象深刻的性能。
  • WebSocket支持。
  • GraphQL支持。
  • 处理中的后台任务。
  • 启动和关闭事件。
  • 测试基于请求的客户端。
  • CORS,GZip,静态文件,流式响应。
  • 会话和Cookie支持。
  • 100%的测试覆盖率。
  • 100%类型注释的代码库。
  • 零硬依赖性。

示例

starlette_example.py

1
2
3
4
5
6
7
8
9
10
11
12
13
from starlette.applications import Starlette
from starlette.responses import JSONResponse
from starlette.routing import Route


async def homepage(request):
    return JSONResponse({'hello': 'world'})

routes = [
    Route("/", endpoint=homepage)
]

app = Starlette(debug=True, routes=routes)

服务器启动:

1
uvicorn starlette_example:app

如果使用

浏览器访问http://127.0.0.1:8000/,它将显示为{"hello":"world"}

如果您曾经接触过Python(类似于Flask)的Web框架,我认为这是您在某处看到的一种表示法。

与ASGI服务器

的关系

我离ASGI服务器示例中的代码太远了。

但是,ASGI服务器(如Uvicorn文档中所述)也可以运行实例样式的应用程序,例如:

1
2
3
4
5
6
class App:
    async def __call__(self, scope, receive, send):
        assert scope['type'] == 'http'
        ...

app = App()

Starlette使用此表示法。在Starlette示例中,您不必直接弄乱__call__方法,只需在实例化时将homepage函数(以及路由定义)传递给应用程序类,它将完成从路由到函数执行的所有操作。 (应用程序类实现为Starlette クラス。)

这样,就可以实现实现,以便可以使用实例变量和方法灵活地构建应用程序。

Starlette也可以用作ASGI服务器的工具包(生态系统),如下所示:

1
2
3
4
5
6
7
from starlette.responses import PlainTextResponse


async def app(scope, receive, send):
    assert scope['type'] == 'http'
    response = PlainTextResponse('Hello, world!')
    await response(scope, receive, send)

Fast API站在Starlette肩上的事实意味着它使用了如上所述的Starlette Framework / Toolkit。在最大程度上,FastAPI中的应用程序类FastAPI クラス继承自Starlette クラス

此外,后台进程,测试客户端等仍在使用Starlette生态系统。

数据验证/序列化

接下来是关于"数据"的信息。

数据验证实际上是指数据验证。这是检查是否包括指定数据,数据类型是否为指定类型以及是否在指定值范围内的过程。

数据序列化是根据指定的数据模式转换数据类型的过程。

我认为Django REST框架序列化器是众所周知的支持这些的Python Web框架。这是一项重要功能,但是集成验证/序列化的Python Web框架并不多。

Pydantic

Pydantic是一个使用Python类型提示执行数据验证/序列化的库。

它似乎还用于Web应用程序以外的目的。

  • Pydantic-使用Pydantic

如果您使用过FastAPI,可以轻松想象FastAPI在Pydantic肩膀上的地位。因此,我只给您简单介绍。

示例

金字塔式-示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from datetime import datetime
from typing import List, Optional
from pydantic import BaseModel


class User(BaseModel):
    id: int
    name = 'John Doe'
    signup_ts: Optional[datetime] = None
    friends: List[int] = []


external_data = {
    'id': '123',
    'signup_ts': '2019-06-01 12:22',
    'friends': [1, 2, '3'],
}
user = User(**external_data)
print(user.id)
#> 123
print(repr(user.signup_ts))
#> datetime.datetime(2019, 6, 1, 12, 22)
print(user.friends)
#> [1, 2, 3]
print(user.dict())
"""
{
    'id': 123,
    'signup_ts': datetime.datetime(2019, 6, 1, 12, 22),
    'friends': [1, 2, 3],
    'name': 'John Doe',
}
"""

只需继承

Basemodel并注释数据类型。仅此一项就可以转换传递数据的类型。另外,如果不包括指定的数据,将返回错误。

Python类型提示只是注释,实际上可以接受任何类型。有时它很松散且方便,但是Web API必须考虑传递无效数据类型的情况,这会增加代码行数。

由于它是

,因此仅使用Pydantic可以节省大量的行。

与快速API

集成

Pydantic的数据验证/序列化本身非常强大,但是与以下与Fast API集成在一起时,它甚至更有用:

  • 只需将其用于参数类型注释,即可自动完成请求验证/序列化。
  • 如果发生验证错误,它将自动向客户端返回错误响应
  • OpenAPI标准数据模式是自动生成的

快速API站在Pydantic的肩膀上,因为Pydantic使得易于使用非常重要的功能(可以将其与其他Web框架区分开)。但是,没有Pydantic不一定不一定有效(尽管它实际上可能在内部负责重要的处理),因此我认为这与Starlette一样不那么重要。

终于

Fast API研究了如何使用这些库来找出站在巨人(Starlette和Pydantic)肩上的含义。
希望对您有帮助。