網(wǎng)站首頁 編程語言 正文
一、簡介
pydantic 庫是 python 中用于數(shù)據(jù)接口定義檢查與設置管理的庫。
pydantic 在運行時強制執(zhí)行類型提示,并在數(shù)據(jù)無效時提供友好的錯誤。
它具有如下優(yōu)點:
- 與 IDE/linter 完美搭配,不需要學習新的模式,只是使用類型注解定義類的實例
- 多用途,BaseSettings 既可以驗證請求數(shù)據(jù),也可以從環(huán)境變量中讀取系統(tǒng)設置
- 快速
- 可以驗證復雜結構
- 可擴展,可以使用validator裝飾器裝飾的模型上的方法來擴展驗證
- 數(shù)據(jù)類集成,除了BaseModel,pydantic還提供了一個dataclass裝飾器,它創(chuàng)建帶有輸入數(shù)據(jù)解析和驗證的普通 Python 數(shù)據(jù)類。
二、安裝
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是一個整數(shù)并且是必需的,name是一個帶有默認值的字符串并且不是必需的
實例化使用:
user = User(id='123')
實例化將執(zhí)行所有解析和驗證,如果有錯誤則會觸發(fā) ValidationError 報錯。
模型具有以下屬性:
dict() 模型字段和值的字典
json() JSON 字符串表示dict()
copy() 模型的副本(默認為淺表副本)
parse_obj() 使用dict解析數(shù)據(jù)
parse_raw 將str或bytes并將其解析為json,然后將結果傳遞給parse_obj
parse_file 文件路徑,讀取文件并將內(nèi)容傳遞給parse_raw。如果content_type省略,則從文件的擴展名推斷
from_orm() 從ORM 對象創(chuàng)建模型
schema() 返回模式的字典
schema_json() 返回該字典的 JSON 字符串表示
construct() 允許在沒有驗證的情況下創(chuàng)建模型
__fields_set__ 初始化模型實例時設置的字段名稱集
__fields__ 模型字段的字典
__config__ 模型的配置類
2、遞歸模型
可以使用模型本身作為注釋中的類型來定義更復雜的數(shù)據(jù)結構。
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 的實例作為參數(shù),傳遞給 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 整數(shù)類型
float 浮點數(shù)類型
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 任意網(wǎng)址
SecretStr、SecretBytes 敏感信息,將被格式化為'**********'或''
Json 類型
PaymentCardNumber 支付卡類型
-
約束類型,可以使用con*類型函數(shù)限制許多常見類型的值
- conlist
- item_type: Type[T]: 列表項的類型
- min_items: int = None: 列表中的最小項目數(shù)
- max_items: int = None: 列表中的最大項目數(shù)
- conset
- item_type: Type[T]: 設置項目的類型
- min_items: int = None: 集合中的最小項目數(shù)
- max_items: int = None: 集合中的最大項目數(shù)
- conint
- strict: bool = False: 控制類型強制
- gt: int = None: 強制整數(shù)大于設定值
- ge: int = None: 強制整數(shù)大于或等于設定值
- lt: int = None: 強制整數(shù)小于設定值
- le: int = None: 強制整數(shù)小于或等于設定值
- multiple_of: int = None: 強制整數(shù)為設定值的倍數(shù)
- confloat
- strict: bool = False: 控制類型強制
- gt: float = None: 強制浮點數(shù)大于設定值
- ge: float = None: 強制 float 大于或等于設定值
- lt: float = None: 強制浮點數(shù)小于設定值
- le: float = None: 強制 float 小于或等于設定值
- multiple_of: float = None: 強制 float 為設定值的倍數(shù)
- condecimal
- gt: Decimal = None: 強制十進制大于設定值
- ge: Decimal = None: 強制十進制大于或等于設定值
- lt: Decimal = None: 強制十進制小于設定值
- le: Decimal = None: 強制十進制小于或等于設定值
- max_digits: int = None: 小數(shù)點內(nèi)的最大位數(shù)。它不包括小數(shù)點前的零或尾隨的十進制零
- decimal_places: int = None: 允許的最大小數(shù)位數(shù)。它不包括尾隨十進制零
- multiple_of: Decimal = None: 強制十進制為設定值的倍數(shù)
- 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裝飾器可以實現(xiàn)自定義驗證和對象之間的復雜關系。
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) """
關于驗證器的一些注意事項:
- 驗證器是“類方法”,因此它們接收的第一個參數(shù)值是UserModel類,而不是UserModel
- 第二個參數(shù)始終是要驗證的字段值,可以隨意命名
- 單個驗證器可以通過傳遞多個字段名稱來應用于多個字段,也可以通過傳遞特殊值在所有字段上調(diào)用單個驗證器'*'
- 關鍵字參數(shù)pre將導致在其他驗證之前調(diào)用驗證器
- 通過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) """
- 關鍵字參數(shù) always 將導致始終驗證,出于性能原因,默認情況下,當未提供值時,不會為字段調(diào)用驗證器。然而,在某些情況下,始終調(diào)用驗證器可能很有用或需要,例如設置動態(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)境中讀取,來確定未作為關鍵字參數(shù)傳遞的任何字段的值。(如果未設置匹配的環(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
總結
原文鏈接:https://juejin.cn/post/7079027549896081421
相關推薦
- 2023-02-17 Python?樹表查找(二叉排序樹、平衡二叉樹)_python
- 2023-03-22 Ansible?Galaxy命令的使用實踐示例詳解_服務器其它
- 2022-05-10 Element-ui 中<template slot-scope=“scope“> 的用法問題以及剖
- 2022-11-16 Python?讀取?.gz?文件全過程_python
- 2022-06-01 利用Python實現(xiàn)外觀數(shù)列求解_python
- 2023-07-09 Python Django 零基礎從零到一部署服務,Hello Django!全文件夾目錄和核心代碼
- 2022-04-07 代碼詳解Python的函數(shù)基礎(1)_python
- 2022-10-09 ASP.NET泛型四之使用Lazy<T>實現(xiàn)延遲加載_實用技巧
- 最近更新
-
- window11 系統(tǒng)安裝 yarn
- 超詳細win安裝深度學習環(huán)境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區(qū)別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優(yōu)雅實現(xiàn)加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發(fā)現(xiàn)-Nac
- Spring Security之基于HttpR
- Redis 底層數(shù)據(jù)結構-簡單動態(tài)字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發(fā)送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支