天天看點

Pydantic庫簡介

  • pydantic庫是什麼

pydantic庫是一種常用的用于資料接口schema定義與檢查的庫。

通過pydantic庫,我們可以更為規範地定義和使用資料接口,這對于大型項目的開發将會更為友好。

當然,除了pydantic庫之外,像是valideer庫、marshmallow庫、trafaret庫以及cerberus庫等都可以完成相似的功能,但是相較之下,pydantic庫的執行效率會更加優秀一些。

是以,這裡,我們僅針對pydantic庫來介紹一下如何規範定義标準schema并使用。

  • pydantic庫用法考察

1. 基本使用方法

1.1 schema基本定義方法

pydantic庫的資料定義方式是通過

BaseModel

類來進行定義的,所有基于pydantic的資料類型本質上都是一個

BaseModel

類,它最基本的使用方式如下:

from pydantic import BaseModel

class Person(BaseModel):
    name: str      

1.2 基本的schema執行個體化方法

調用時,我們隻需要對其進行執行個體化即可,執行個體化方法有以下幾種:

    1. 直接傳值 p = Person(name="Tom") print(p.json()) # {"name": "Tom"}
    2. 通過字典傳入 p = {"name": "Tom"} p = Person(**p) print(p.json()) # {"name": "Tom"}
    3. 通過其他的執行個體化對象傳入 p2 = Person.copy(p) print(p2.json()) # {"name": "Tom"}

當傳入值錯誤的時候,pydantic就會抛出報錯,例如:

Person(person="Tom")      

pydantic會抛出異常:

ValidationError: 1 validation errors for Person
name
  field required (type=value_error.missing)      

另一方面,如果傳入值多于定義值時,BaseModel也會自動對其進行過濾。如:

p = Person(name="Tom", gender="man", age=24)
print(p.json()) # {"name": "Tom"}      

可以看到,額外的參數gender與age都被自動過濾了。

通過這種方式,資料的傳遞将會更為安全,但是,同樣的,這也要求我們在前期的schema定義中必須要盡可能地定義完全。

此外,pydantic在資料傳輸時會直接進行資料類型轉換,是以,如果資料傳輸格式錯誤,但是可以通過轉換變換為正确的資料類型是,資料傳輸也可以成功,例如:

p = Person(name=123)
print(p.json()) # {"name": "123"}      

1.3 pydantic基本資料類型

下面,我們來看一下pydantic中的一些常用的基本類型。

from pydantic import BaseModel
from typing import Dict, List, Sequence, Set, Tuple

class Demo(BaseModel):
    a: int # 整型
    b: float # 浮點型
    c: str # 字元串
    d: bool # 布爾型
    e: List[int] # 整型清單
    f: Dict[str, int] # 字典型,key為str,value為int
    g: Set[int] # 集合
    h: Tuple[str, int] # 元組      

更多的有關pydantic基本資料類型的介紹可以參考官網說明文檔。

2. 進階資料結構考察

這裡,我們給出一些較為複雜的資料類型的實作。

2.1 enum資料類型

enum型資料類型我們可以通過enum庫進行實作,給出一個例子如下:

from enum import Enum

class Gender(str, Enum):
    man = "man"
    women = "women"      

2.2 可選資料類型

如果一個資料類型不是必須的,可以允許使用者在使用中不進行傳入,則我們可以使用typing庫中的Optional方法進行實作。

給出一個例子如下:

from typing import Optional
from pydantic import BaseModel

class Person(BaseModel):
    name: str
    age: Optional[int]      

需要注意的是,設定為可選之後,資料中仍然會有age字段,但是其預設值為None,即當不傳入age字段時,Person仍然可以取到age,隻是其值為None。

例:

p = Person(name="Tom")
print(p.json()) # {"name": "Tom", "age": None}      

2.3 資料預設值的設定

上述可選資料類型方法事實上是一種較為特殊的給予資料預設值的方法,隻是給其的預設值為None。

這裡,我們給出一些更加一般性的給出資料預設值的方法。

其實作方式也極其簡單,下面,我們直接給出例子如下:

from pydantic import BaseModel

class Person(BaseModel):
    name: str
    gender: str = "man"

p = Person(name="Tom")
print(p.json()) # {"name": "Tom", "gender": "man"}      

2.4 允許多種資料類型

如果一個資料可以允許多種資料類型,我們可以通過typing庫中的Union方法進行實作。

給出一個例子如下:

from typing import Union
from pydantic import BaseModel

class Time(BaseModel):
    time: Union[int, str]
        
t = Time(time=12345)
print(t.json()) # {"time": 12345}
t = Time(time = "2020-7-29")
print(t.json()) # {"time": "2020-7-29"}      

2.5 異名資料傳遞方法

假設我們之前已經定義了一個schema,将其中某一個參量命名為了A,但是在後續的定義中,我們希望這個量被命名為B,要如何完成這兩個不同名稱參量的互相傳遞呢?

我們可以通過Field方法來實作這一操作。

給出例子如下:

from pydantic import BaseModel, Field

class Password(BaseModel):
    password: str = Field(alias = "key")      

則在傳入時,我們需要用key關鍵詞來傳入password變量。

給出執行個體化代碼如下:

p = Password(key="123456")
print(p.json()) # {"password": "123456"}      

3. 多級schema定義樣例

這裡,我們給出一個較為複雜的基于pydantic的schema定義實作樣例。

from enum import Enum
from typing import List, Union
from datetime import date
from pydantic import BaseModel

class Gender(str, Enum):
    man = "man"
    women = "women"

class Person(BaseModel):
    name : str
    gender : Gender
        
class Department(BaseModel):
    name : str
    lead : Person
    cast : List[Person]
        
class Group(BaseModel):
    owner: Person
    member_list: List[Person] = []

class Company(BaseModel):
    name: str
    owner: Union[Person, Group]
    regtime: date
    department_list: List[Department] = []      

需要注意的是,我們除了可以一步一步地執行個體化之外,如果我們已經有了一個完整的Company的内容字典,我們也可以一步到位地進行執行個體化。

例如:

sales_department = {
    "name": "sales",
    "lead": {"name": "Sarah", "gender": "women"},
    "cast": [
        {"name": "Sarah", "gender": "women"},
        {"name": "Bob", "gender": "man"},
        {"name": "Mary", "gender": "women"}
    ]
}

research_department = {
    "name": "research",
    "lead": {"name": "Allen", "gender": "man"},
    "cast": [
        {"name": "Jane", "gender": "women"},
        {"name": "Tim", "gender": "man"}
    ]
}

company = {
    "name": "Fantasy",
    "owner": {"name": "Victor", "gender": "man"},
    "regtime": "2020-7-23",
    "department_list": [
        sales_department,
        research_department
    ]
}

company = Company(**company)      

上述代碼也能執行成功。

4. 資料檢查方法考察

pydantic本身提供了上述基本類型的資料檢查方法,但是,除此之外,我們也可以使用validator和config方法來實作更為複雜的資料類型定義以及檢查。

4.1 validator用法考察

使用validator方法,我們可以對資料進行更為複雜的資料檢查。

下面,我們給出一個代碼實作樣例如下:

import re
from pydantic import BaseModel, validator

class Password(BaseModel):
    password: str
        
    @validator("password")
    def password_rule(cls, password):
        def is_valid(password):
            if len(password) < 6 or len(password) > 20:
                return False
            if not re.search("[a-z]", password):
                return False
            if not re.search("[A-Z]", password):
                return False
            if not re.search("\d", password):
                return False
            return True
        if not is_valid(password):
            raise ValueError("password is invalid")      

通過這種方式,我們就可以額外對密碼類進行格式要求,對其字元數以及内部字元進行要求。

4.2 Config方法考察

如果要對BaseModel中的某一基本型進行統一的格式要求,我們還可以使用Config方法來實作。

例如:

from pydantic import BaseModel

class Password(BaseModel):
    password: str
        
    class Config:
        min_anystr_length = 6 # 令Password類中所有的字元串長度均要不少于6
        max_anystr_length = 20 # 令Password類中所有的字元串長度均要不大于20      

有關Config類中的特殊關鍵詞名稱,這裡隻給出了兩個簡單的例子,更多的内容可以參考官網中的文檔說明。

5. 參考連結

    1. https://pydantic-docs.helpmanual.io/
    2. Python筆記:Pydantic庫簡介 - 騰訊雲開發者社群-騰訊雲 (tencent.com)

本文來自部落格園,作者:術科術,轉載請注明原文連結:https://www.cnblogs.com/shukeshu/p/16571629.html