您好,登錄后才能下訂單哦!
這篇文章主要介紹了python庫pydantic怎么用,具有一定借鑒價(jià)值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
pydantic 庫是 python 中用于數(shù)據(jù)接口定義檢查與設(shè)置管理的庫。
pydantic 在運(yùn)行時(shí)強(qiáng)制執(zhí)行類型提示,并在數(shù)據(jù)無效時(shí)提供友好的錯(cuò)誤。
它具有如下優(yōu)點(diǎn):
與 IDE/linter 完美搭配,不需要學(xué)習(xí)新的模式,只是使用類型注解定義類的實(shí)例
多用途,BaseSettings 既可以驗(yàn)證請(qǐng)求數(shù)據(jù),也可以從環(huán)境變量中讀取系統(tǒng)設(shè)置
快速
可以驗(yàn)證復(fù)雜結(jié)構(gòu)
可擴(kuò)展,可以使用validator裝飾器裝飾的模型上的方法來擴(kuò)展驗(yàn)證
數(shù)據(jù)類集成,除了BaseModel,pydantic還提供了一個(gè)dataclass裝飾器,它創(chuàng)建帶有輸入數(shù)據(jù)解析和驗(yàn)證的普通 Python 數(shù)據(jù)類。
pip install pydantic
要測(cè)試 pydantic 是否已編譯,請(qǐng)運(yùn)行:
import pydantic print('compiled:', pydantic.compiled)
支持使用dotenv文件獲取配置,需要安裝 python-dotenv
pip install pydantic[dotenv]
pydantic中定義對(duì)象都是通過模型的,你可以認(rèn)為模型就是類型語言中的類型。
from pydantic import BaseModel class User(BaseModel): id: int name = 'Jane Doe'
上面的例子,定義了一個(gè)User模型,繼承自BaseModel,有2個(gè)字段,id是一個(gè)整數(shù)并且是必需的,name是一個(gè)帶有默認(rèn)值的字符串并且不是必需的
實(shí)例化使用:
user = User(id='123')
實(shí)例化將執(zhí)行所有解析和驗(yàn)證,如果有錯(cuò)誤則會(huì)觸發(fā) ValidationError 報(bào)錯(cuò)。
模型具有以下屬性:
dict() 模型字段和值的字典
json() JSON 字符串表示dict()
copy() 模型的副本(默認(rèn)為淺表副本)
parse_obj() 使用dict解析數(shù)據(jù)
parse_raw 將str或bytes并將其解析為json,然后將結(jié)果傳遞給parse_obj
parse_file 文件路徑,讀取文件并將內(nèi)容傳遞給parse_raw。如果content_type省略,則從文件的擴(kuò)展名推斷
from_orm() 從ORM 對(duì)象創(chuàng)建模型
schema() 返回模式的字典
schema_json() 返回該字典的 JSON 字符串表示
construct() 允許在沒有驗(yàn)證的情況下創(chuàng)建模型
__fields_set__ 初始化模型實(shí)例時(shí)設(shè)置的字段名稱集
__fields__ 模型字段的字典
__config__ 模型的配置類
可以使用模型本身作為注釋中的類型來定義更復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。
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]
使用 typing.TypeVar 的實(shí)例作為參數(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 動(dòng)態(tài)模型
在某些情況下,直到運(yùn)行時(shí)才知道模型的結(jié)構(gòu)。為此 pydantic 提供了create_model允許動(dòng)態(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 浮點(diǎn)數(shù)類型
str 字符串類型
bytes 字節(jié)類型
list 允許list,tuple,set,frozenset,deque, 或生成器并轉(zhuǎn)換為列表
tuple 允許list,tuple,set,frozenset,deque, 或生成器并轉(zhuǎn)換為元組
dict 字典類型
set 允許list,tuple,set,frozenset,deque, 或生成器和轉(zhuǎn)換為集合;
frozenset 允許list,tuple,set,frozenset,deque, 或生成器和強(qiáng)制轉(zhuǎn)換為凍結(jié)集
deque 允許list,tuple,set,frozenset,deque, 或生成器和強(qiáng)制轉(zhuǎn)換為雙端隊(duì)列
datetime 的date,datetime,time,timedelta 等日期類型
typing 中的 Deque, Dict, FrozenSet, List, Optional, Sequence, Set, Tuple, Union,Callable,Pattern等類型
FilePath,文件路徑
DirectoryPath 目錄路徑
EmailStr 電子郵件地址
NameEmail 有效的電子郵件地址或格式
PyObject 需要一個(gè)字符串并加載可在該虛線路徑中導(dǎo)入的 python 對(duì)象;
Color 顏色類型
AnyUrl 任意網(wǎng)址
SecretStr、SecretBytes 敏感信息,將被格式化為'**********'或''
Json 類型
PaymentCardNumber 支付卡類型
約束類型,可以使用con*類型函數(shù)限制許多常見類型的值
conlist
item_type: Type[T]: 列表項(xiàng)的類型
min_items: int = None: 列表中的最小項(xiàng)目數(shù)
max_items: int = None: 列表中的最大項(xiàng)目數(shù)
conset
item_type: Type[T]: 設(shè)置項(xiàng)目的類型
min_items: int = None: 集合中的最小項(xiàng)目數(shù)
max_items: int = None: 集合中的最大項(xiàng)目數(shù)
conint
strict: bool = False: 控制類型強(qiáng)制
gt: int = None: 強(qiáng)制整數(shù)大于設(shè)定值
ge: int = None: 強(qiáng)制整數(shù)大于或等于設(shè)定值
lt: int = None: 強(qiáng)制整數(shù)小于設(shè)定值
le: int = None: 強(qiáng)制整數(shù)小于或等于設(shè)定值
multiple_of: int = None: 強(qiáng)制整數(shù)為設(shè)定值的倍數(shù)
confloat
strict: bool = False: 控制類型強(qiáng)制
gt: float = None: 強(qiáng)制浮點(diǎn)數(shù)大于設(shè)定值
ge: float = None: 強(qiáng)制 float 大于或等于設(shè)定值
lt: float = None: 強(qiáng)制浮點(diǎn)數(shù)小于設(shè)定值
le: float = None: 強(qiáng)制 float 小于或等于設(shè)定值
multiple_of: float = None: 強(qiáng)制 float 為設(shè)定值的倍數(shù)
condecimal
gt: Decimal = None: 強(qiáng)制十進(jìn)制大于設(shè)定值
ge: Decimal = None: 強(qiáng)制十進(jìn)制大于或等于設(shè)定值
lt: Decimal = None: 強(qiáng)制十進(jìn)制小于設(shè)定值
le: Decimal = None: 強(qiáng)制十進(jìn)制小于或等于設(shè)定值
max_digits: int = None: 小數(shù)點(diǎn)內(nèi)的最大位數(shù)。它不包括小數(shù)點(diǎn)前的零或尾隨的十進(jìn)制零
decimal_places: int = None: 允許的最大小數(shù)位數(shù)。它不包括尾隨十進(jìn)制零
multiple_of: Decimal = None: 強(qiáng)制十進(jìn)制為設(shè)定值的倍數(shù)
constr
strip_whitespace: bool = False: 刪除前尾空格
to_lower: bool = False: 將所有字符轉(zhuǎn)為小寫
strict: bool = False: 控制類型強(qiáng)制
min_length: int = None: 字符串的最小長(zhǎng)度
max_length: int = None: 字符串的最大長(zhǎng)度
curtail_length: int = None: 當(dāng)字符串長(zhǎng)度超過設(shè)定值時(shí),將字符串長(zhǎng)度縮小到設(shè)定值
regex: str = None: 正則表達(dá)式來驗(yàn)證字符串
conbytes
strip_whitespace: bool = False: 刪除前尾空格
to_lower: bool = False: 將所有字符轉(zhuǎn)為小寫
min_length: int = None: 字節(jié)串的最小長(zhǎng)度
max_length: int = None: 字節(jié)串的最大長(zhǎng)度
嚴(yán)格類型,您可以使用StrictStr,StrictBytes,StrictInt,StrictFloat,和StrictBool類型,以防止強(qiáng)制兼容類型
使用validator裝飾器可以實(shí)現(xiàn)自定義驗(yàn)證和對(duì)象之間的復(fù)雜關(guā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) """
關(guān)于驗(yàn)證器的一些注意事項(xiàng):
驗(yàn)證器是“類方法”,因此它們接收的第一個(gè)參數(shù)值是UserModel類,而不是UserModel
第二個(gè)參數(shù)始終是要驗(yàn)證的字段值,可以隨意命名
單個(gè)驗(yàn)證器可以通過傳遞多個(gè)字段名稱來應(yīng)用于多個(gè)字段,也可以通過傳遞特殊值在所有字段上調(diào)用單個(gè)驗(yàn)證器'*'
關(guān)鍵字參數(shù)pre將導(dǎo)致在其他驗(yàn)證之前調(diào)用驗(yàn)證器
通過each_item=True將導(dǎo)致驗(yàn)證器被施加到單獨(dú)的值(例如List,Dict,Set等),而不是整個(gè)對(duì)象
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) """
關(guān)鍵字參數(shù) always 將導(dǎo)致始終驗(yàn)證,出于性能原因,默認(rèn)情況下,當(dāng)未提供值時(shí),不會(huì)為字段調(diào)用驗(yàn)證器。然而,在某些情況下,始終調(diào)用驗(yàn)證器可能很有用或需要,例如設(shè)置動(dòng)態(tài)默認(rèn)值。
allow_reuse 可以在多個(gè)字段/模型上使用相同的驗(yàn)證器
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)建一個(gè)繼承自BaseSettings的模型,模型初始化程序?qū)L試通過從環(huán)境中讀取,來確定未作為關(guān)鍵字參數(shù)傳遞的任何字段的值。(如果未設(shè)置匹配的環(huán)境變量,則仍將使用默認(rèn)值。)
這使得很容易:
創(chuàng)建明確定義、類型提示的應(yīng)用程序配置類
自動(dòng)從環(huán)境變量中讀取對(duì)配置的修改
在需要的地方手動(dòng)覆蓋初始化程序中的特定設(shè)置(例如在單元測(cè)試中)
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 文件設(shè)置變量,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ì)讀取環(huán)境變量,環(huán)境變量將始終優(yōu)先于從 dotenv 文件加載的值。
pydantic 支持設(shè)置敏感信息文件,同樣有2種方式加載:
class Settings(BaseSettings): ... database_password: str class Config: secrets_dir = '/var/run'
或者:
settings = Settings(_secrets_dir='/var/run')
即使使用 secrets 目錄,pydantic仍會(huì)從 dotenv 文件或環(huán)境中讀取環(huán)境變量,dotenv 文件和環(huán)境變量將始終優(yōu)先于從 secrets 目錄加載的值。
Pydantic 附帶了一個(gè) mypy 插件,向 mypy 添加了許多重要的特定于 pydantic 的功能,以提高其對(duì)代碼進(jìn)行類型檢查的能力。
例如以下腳本:
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 會(huì)捕獲其中一個(gè)錯(cuò)誤:
13: error: "Model" has no attribute "middle_name"
啟用插件后,它會(huì)同時(shí)捕獲:
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
要更改插件設(shè)置的值,請(qǐng)?jiān)?mypy 配置文件中創(chuàng)建一個(gè)名為 的部分[pydantic-mypy],并為要覆蓋的設(shè)置添加鍵值對(duì):
[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
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“python庫pydantic怎么用”這篇文章對(duì)大家有幫助,同時(shí)也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識(shí)等著你來學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。