python庫pydantic的簡易入門教程
一、簡介
pydantic 庫是 python 中用于數據接口定義檢查與設置管理的庫。
pydantic 在運行時強制執(zhí)行類型提示,并在數據無效時提供友好的錯誤。
它具有如下優(yōu)點:
- 與 IDE/linter 完美搭配,不需要學習新的模式,只是使用類型注解定義類的實例
- 多用途,BaseSettings 既可以驗證請求數據,也可以從環(huán)境變量中讀取系統設置
- 快速
- 可以驗證復雜結構
- 可擴展,可以使用validator裝飾器裝飾的模型上的方法來擴展驗證
- 數據類集成,除了BaseModel,pydantic還提供了一個dataclass裝飾器,它創(chuàng)建帶有輸入數據解析和驗證的普通 Python 數據類。
二、安裝
pip install pydantic
要測試 pydantic 是否已編譯,請運行:
import pydantic
print('compiled:', pydantic.compiled)支持使用dotenv文件獲取配置,需要安裝 python-dotenv
pip install pydantic[dotenv]
三、常見模型
pydantic中定義對象都是通過模型的,你可以認為模型就是類型語言中的類型。
1、BaseModel 基本模型
from pydantic import BaseModel
class User(BaseModel):
id: int
name = 'Jane Doe'上面的例子,定義了一個User模型,繼承自BaseModel,有2個字段,id是一個整數并且是必需的,name是一個帶有默認值的字符串并且不是必需的
實例化使用:
user = User(id='123')
實例化將執(zhí)行所有解析和驗證,如果有錯誤則會觸發(fā) ValidationError 報錯。
模型具有以下屬性:
dict() 模型字段和值的字典
json() JSON 字符串表示dict()
copy() 模型的副本(默認為淺表副本)
parse_obj() 使用dict解析數據
parse_raw 將str或bytes并將其解析為json,然后將結果傳遞給parse_obj
parse_file 文件路徑,讀取文件并將內容傳遞給parse_raw。如果content_type省略,則從文件的擴展名推斷
from_orm() 從ORM 對象創(chuàng)建模型
schema() 返回模式的字典
schema_json() 返回該字典的 JSON 字符串表示
construct() 允許在沒有驗證的情況下創(chuàng)建模型
__fields_set__ 初始化模型實例時設置的字段名稱集
__fields__ 模型字段的字典
__config__ 模型的配置類
2、遞歸模型
可以使用模型本身作為注釋中的類型來定義更復雜的數據結構。
from typing import List
from pydantic import BaseModel
class Foo(BaseModel):
count: int
size: float = None
class Bar(BaseModel):
apple = 'x'
banana = 'y'
class Spam(BaseModel):
foo: Foo
bars: List[Bar]3、GenericModel 通用模型(泛型):
使用 typing.TypeVar 的實例作為參數,傳遞給 typing.Generic,然后在繼承了pydantic.generics.GenericModel 的模型中使用:
from typing import Generic, TypeVar, Optional, List
from pydantic import BaseModel, validator, ValidationError
from pydantic.generics import GenericModel
DataT = TypeVar('DataT')
class Error(BaseModel):
code: int
message: str
class DataModel(BaseModel):
numbers: List[int]
people: List[str]
class Response(GenericModel, Generic[DataT]):
data: Optional[DataT]
error: Optional[Error]
@validator('error', always=True)
def check_consistency(cls, v, values):
if v is not None and values['data'] is not None:
raise ValueError('must not provide both data and error')
if v is None and values.get('data') is None:
raise ValueError('must provide data or error')
return v
data = DataModel(numbers=[1, 2, 3], people=[])
error = Error(code=404, message='Not found')
print(Response[int](data=1))
#> data=1 error=None
print(Response[str](data='value'))
#> data='value' error=None
print(Response[str](data='value').dict())
#> {'data': 'value', 'error': None}
print(Response[DataModel](data=data).dict())
"""
{
'data': {'numbers': [1, 2, 3], 'people': []},
'error': None,
}
"""
print(Response[DataModel](error=error).dict())
"""
{
'data': None,
'error': {'code': 404, 'message': 'Not found'},
}
"""
try:
Response[int](data='value')
except ValidationError as e:
print(e)
"""
2 validation errors for Response[int]
data
value is not a valid integer (type=type_error.integer)
error
must provide data or error (type=value_error)
"""4、create_model 動態(tài)模型
在某些情況下,直到運行時才知道模型的結構。為此 pydantic 提供了create_model允許動態(tài)創(chuàng)建模型的方法。
from pydantic import BaseModel, create_model
DynamicFoobarModel = create_model('DynamicFoobarModel', foo=(str, ...), bar=123)四、常用類型
None,type(None)或Literal[None]只允許None值
bool 布爾類型
int 整數類型
float 浮點數類型
str 字符串類型
bytes 字節(jié)類型
list 允許list,tuple,set,frozenset,deque, 或生成器并轉換為列表
tuple 允許list,tuple,set,frozenset,deque, 或生成器并轉換為元組
dict 字典類型
set 允許list,tuple,set,frozenset,deque, 或生成器和轉換為集合;
frozenset 允許list,tuple,set,frozenset,deque, 或生成器和強制轉換為凍結集
deque 允許list,tuple,set,frozenset,deque, 或生成器和強制轉換為雙端隊列
datetime 的date,datetime,time,timedelta 等日期類型
typing 中的 Deque, Dict, FrozenSet, List, Optional, Sequence, Set, Tuple, Union,Callable,Pattern等類型
FilePath,文件路徑
DirectoryPath 目錄路徑
EmailStr 電子郵件地址
NameEmail 有效的電子郵件地址或格式
PyObject 需要一個字符串并加載可在該虛線路徑中導入的 python 對象;
Color 顏色類型
AnyUrl 任意網址
SecretStr、SecretBytes 敏感信息,將被格式化為'**********'或''
Json 類型
PaymentCardNumber 支付卡類型
約束類型,可以使用con*類型函數限制許多常見類型的值
- conlist
- item_type: Type[T]: 列表項的類型
- min_items: int = None: 列表中的最小項目數
- max_items: int = None: 列表中的最大項目數
- conset
- item_type: Type[T]: 設置項目的類型
- min_items: int = None: 集合中的最小項目數
- max_items: int = None: 集合中的最大項目數
- conint
- strict: bool = False: 控制類型強制
- gt: int = None: 強制整數大于設定值
- ge: int = None: 強制整數大于或等于設定值
- lt: int = None: 強制整數小于設定值
- le: int = None: 強制整數小于或等于設定值
- multiple_of: int = None: 強制整數為設定值的倍數
- confloat
- strict: bool = False: 控制類型強制
- gt: float = None: 強制浮點數大于設定值
- ge: float = None: 強制 float 大于或等于設定值
- lt: float = None: 強制浮點數小于設定值
- le: float = None: 強制 float 小于或等于設定值
- multiple_of: float = None: 強制 float 為設定值的倍數
- condecimal
- gt: Decimal = None: 強制十進制大于設定值
- ge: Decimal = None: 強制十進制大于或等于設定值
- lt: Decimal = None: 強制十進制小于設定值
- le: Decimal = None: 強制十進制小于或等于設定值
- max_digits: int = None: 小數點內的最大位數。它不包括小數點前的零或尾隨的十進制零
- decimal_places: int = None: 允許的最大小數位數。它不包括尾隨十進制零
- multiple_of: Decimal = None: 強制十進制為設定值的倍數
- constr
- strip_whitespace: bool = False: 刪除前尾空格
- to_lower: bool = False: 將所有字符轉為小寫
- strict: bool = False: 控制類型強制
- min_length: int = None: 字符串的最小長度
- max_length: int = None: 字符串的最大長度
- curtail_length: int = None: 當字符串長度超過設定值時,將字符串長度縮小到設定值
- regex: str = None: 正則表達式來驗證字符串
- conbytes
- strip_whitespace: bool = False: 刪除前尾空格
- to_lower: bool = False: 將所有字符轉為小寫
- min_length: int = None: 字節(jié)串的最小長度
- max_length: int = None: 字節(jié)串的最大長度
嚴格類型,您可以使用StrictStr,StrictBytes,StrictInt,StrictFloat,和StrictBool類型,以防止強制兼容類型
五、驗證器
使用validator裝飾器可以實現自定義驗證和對象之間的復雜關系。
from pydantic import BaseModel, ValidationError, validator
class UserModel(BaseModel):
name: str
username: str
password1: str
password2: str
@validator('name')
def name_must_contain_space(cls, v):
if ' ' not in v:
raise ValueError('must contain a space')
return v.title()
@validator('password2')
def passwords_match(cls, v, values, **kwargs):
if 'password1' in values and v != values['password1']:
raise ValueError('passwords do not match')
return v
@validator('username')
def username_alphanumeric(cls, v):
assert v.isalnum(), 'must be alphanumeric'
return v
user = UserModel(
name='samuel colvin',
username='scolvin',
password1='zxcvbn',
password2='zxcvbn',
)
print(user)
#> name='Samuel Colvin' username='scolvin' password1='zxcvbn' password2='zxcvbn'
try:
UserModel(
name='samuel',
username='scolvin',
password1='zxcvbn',
password2='zxcvbn2',
)
except ValidationError as e:
print(e)
"""
2 validation errors for UserModel
name
must contain a space (type=value_error)
password2
passwords do not match (type=value_error)
"""關于驗證器的一些注意事項:
- 驗證器是“類方法”,因此它們接收的第一個參數值是UserModel類,而不是UserModel
- 第二個參數始終是要驗證的字段值,可以隨意命名
- 單個驗證器可以通過傳遞多個字段名稱來應用于多個字段,也可以通過傳遞特殊值在所有字段上調用單個驗證器'*'
- 關鍵字參數pre將導致在其他驗證之前調用驗證器
- 通過each_item=True將導致驗證器被施加到單獨的值(例如List,Dict,Set等),而不是整個對象
from typing import List
from pydantic import BaseModel, ValidationError, validator
class ParentModel(BaseModel):
names: List[str]
class ChildModel(ParentModel):
@validator('names', each_item=True)
def check_names_not_empty(cls, v):
assert v != '', 'Empty strings are not allowed.'
return v
# This will NOT raise a ValidationError because the validator was not called
try:
child = ChildModel(names=['Alice', 'Bob', 'Eve', ''])
except ValidationError as e:
print(e)
else:
print('No ValidationError caught.')
#> No ValidationError caught.
class ChildModel2(ParentModel):
@validator('names')
def check_names_not_empty(cls, v):
for name in v:
assert name != '', 'Empty strings are not allowed.'
return v
try:
child = ChildModel2(names=['Alice', 'Bob', 'Eve', ''])
except ValidationError as e:
print(e)
"""
1 validation error for ChildModel2
names
Empty strings are not allowed. (type=assertion_error)
"""- 關鍵字參數 always 將導致始終驗證,出于性能原因,默認情況下,當未提供值時,不會為字段調用驗證器。然而,在某些情況下,始終調用驗證器可能很有用或需要,例如設置動態(tài)默認值。
- allow_reuse 可以在多個字段/模型上使用相同的驗證器
from pydantic import BaseModel, validator
def normalize(name: str) -> str:
return ' '.join((word.capitalize()) for word in name.split(' '))
class Producer(BaseModel):
name: str
# validators
_normalize_name = validator('name', allow_reuse=True)(normalize)
class Consumer(BaseModel):
name: str
# validators
_normalize_name = validator('name', allow_reuse=True)(normalize)六、配置
如果您創(chuàng)建一個繼承自BaseSettings的模型,模型初始化程序將嘗試通過從環(huán)境中讀取,來確定未作為關鍵字參數傳遞的任何字段的值。(如果未設置匹配的環(huán)境變量,則仍將使用默認值。)
這使得很容易:
- 創(chuàng)建明確定義、類型提示的應用程序配置類
- 自動從環(huán)境變量中讀取對配置的修改
- 在需要的地方手動覆蓋初始化程序中的特定設置(例如在單元測試中)
from typing import Set
from pydantic import (
BaseModel,
BaseSettings,
PyObject,
RedisDsn,
PostgresDsn,
Field,
)
class SubModel(BaseModel):
foo = 'bar'
apple = 1
class Settings(BaseSettings):
auth_key: str
api_key: str = Field(..., env='my_api_key')
redis_dsn: RedisDsn = 'redis://user:pass@localhost:6379/1'
pg_dsn: PostgresDsn = 'postgres://user:pass@localhost:5432/foobar'
special_function: PyObject = 'math.cos'
# to override domains:
# export my_prefix_domains='["foo.com", "bar.com"]'
domains: Set[str] = set()
# to override more_settings:
# export my_prefix_more_settings='{"foo": "x", "apple": 1}'
more_settings: SubModel = SubModel()
class Config:
env_prefix = 'my_prefix_' # defaults to no prefix, i.e. ""
fields = {
'auth_key': {
'env': 'my_auth_key',
},
'redis_dsn': {
'env': ['service_redis_dsn', 'redis_url']
}
}
print(Settings().dict())
"""
{
'auth_key': 'xxx',
'api_key': 'xxx',
'redis_dsn': RedisDsn('redis://user:pass@localhost:6379/1',
scheme='redis', user='user', password='pass', host='localhost',
host_type='int_domain', port='6379', path='/1'),
'pg_dsn': PostgresDsn('postgres://user:pass@localhost:5432/foobar',
scheme='postgres', user='user', password='pass', host='localhost',
host_type='int_domain', port='5432', path='/foobar'),
'special_function': <built-in function cos>,
'domains': set(),
'more_settings': {'foo': 'bar', 'apple': 1},
}
"""支持 Dotenv 文件設置變量,pydantic 有兩種方式加載它:
class Settings(BaseSettings):
...
class Config:
env_file = '.env'
env_file_encoding = 'utf-8'或者
settings=Settings(_env_file='prod.env',_env_file_encoding='utf-8')
即使使用 dotenv 文件,pydantic 仍會讀取環(huán)境變量,環(huán)境變量將始終優(yōu)先于從 dotenv 文件加載的值。
pydantic 支持設置敏感信息文件,同樣有2種方式加載:
class Settings(BaseSettings):
...
database_password: str
class Config:
secrets_dir = '/var/run'或者:
settings = Settings(_secrets_dir='/var/run')
即使使用 secrets 目錄,pydantic仍會從 dotenv 文件或環(huán)境中讀取環(huán)境變量,dotenv 文件和環(huán)境變量將始終優(yōu)先于從 secrets 目錄加載的值。
七、與 mypy 一起使用
Pydantic 附帶了一個 mypy 插件,向 mypy 添加了許多重要的特定于 pydantic 的功能,以提高其對代碼進行類型檢查的能力。
例如以下腳本:
from datetime import datetime
from typing import List, Optional
from pydantic import BaseModel, NoneStr
class Model(BaseModel):
age: int
first_name = 'John'
last_name: NoneStr = None
signup_ts: Optional[datetime] = None
list_of_ints: List[int]
m = Model(age=42, list_of_ints=[1, '2', b'3'])
print(m.middle_name) # not a model field!
Model() # will raise a validation error for age and list_of_ints在沒有任何特殊配置的情況下,mypy 會捕獲其中一個錯誤:
13: error: "Model" has no attribute "middle_name"
啟用插件后,它會同時捕獲:
13: error: "Model" has no attribute "middle_name" 16: error: Missing named argument "age" for "Model" 16: error: Missing named argument "list_of_ints" for "Model"
要啟用該插件,只需添加pydantic.mypy到mypy 配置文件中的插件列表:
[mypy] plugins = pydantic.mypy
要更改插件設置的值,請??在 mypy 配置文件中創(chuàng)建一個名為 的部分[pydantic-mypy],并為要覆蓋的設置添加鍵值對:
[mypy] plugins = pydantic.mypy follow_imports = silent warn_redundant_casts = True warn_unused_ignores = True disallow_any_generics = True check_untyped_defs = True no_implicit_reexport = True # for strict mypy: (this is the tricky one :-)) disallow_untyped_defs = True [pydantic-mypy] init_forbid_extra = True init_typed = True warn_required_dynamic_aliases = True warn_untyped_fields = True
總結
到此這篇關于python庫pydantic簡易入門的文章就介紹到這了,更多相關python庫pydantic教程內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
Python使用multiprocessing實現多進程的詳細步驟記錄
multiprocessing包是Python中的多進程管理包,與threading.Thread類似,它可以利用multiprocessing.Process對象來創(chuàng)建一個進程,下面這篇文章主要給大家介紹了關于Python使用multiprocessing實現多進程的詳細步驟,需要的朋友可以參考下2024-08-08
Python使用python-pptx自動化操作和生成PPT
這篇文章主要為大家詳細介紹了如何使用python-pptx庫實現PPT自動化,并提供實用的代碼示例和應用場景,感興趣的小伙伴可以跟隨小編一起學習一下2025-08-08

