Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use python Library pydantic

2025-01-28 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/01 Report--

This article mainly introduces how to use the python library pydantic, has a certain reference value, interested friends can refer to, I hope you can learn a lot after reading this article, the following let the editor take you to understand it.

I. brief introduction

The pydantic library is a library used for data interface definition checking and setting management in python.

Pydantic enforces type prompts at run time and provides friendly errors when the data is invalid.

It has the following advantages:

Perfect with IDE/linter, you don't need to learn new patterns, just use type annotations to define instances of classes

Multi-purpose, BaseSettings can both validate request data and read system settings from environment variables

fast

Can verify complex structures

Extensible, you can use the method on the model decorated by validator decorator to extend validation

Data class integration, in addition to BaseModel,pydantic, provides a dataclass decorator that creates normal Python data classes with input data parsing and validation.

Second, install pip install pydantic

To test whether pydantic has been compiled, run:

Import pydanticprint ('compiled:', pydantic.compiled)

Support the use of dotenv files to get the configuration. You need to install python-dotenv.

Pip install pydanti [dotenv] III. Common models

Objects are defined in pydantic through models, and you can think of models as types in type languages.

1. BaseModel basic model from pydantic import BaseModelclass User (BaseModel): id: int name = 'Jane Doe'

The above example defines a User model that inherits from BaseModel, has two fields, id is an integer and is required, name is a string with a default value and is not required

Instantiate the use:

User = User (id='123')

Instantiation performs all parsing and validation, and triggers an ValidationError error if there is an error.

The model has the following properties:

Dictionary of dict () model fields and values

The json () JSON string represents dict ()

Copy of the copy () model (shallow copy by default)

Parse_obj () uses dict to parse data

Parse_raw parses str or bytes into json, and then passes the result to parse_obj

The parse_file file path, which reads the file and passes the contents to parse_raw. If content_type is omitted, it is deducted from the file extension

From_orm () creates a model from an ORM object

Schema () returns the dictionary of the pattern

Schema_json () returns the JSON string representation of the dictionary

Construct () allows you to create a model without validation

The set of field names set when _ _ fields_set__ initializes the model instance

Dictionary of _ _ fields__ model field

Configuration class of _ _ config__ model

2. Recursive model

You can use the model itself as a type in the annotation to define more complex data structures.

From typing import Listfrom pydantic import BaseModelclass Foo (BaseModel): count: int size: float = Noneclass Bar (BaseModel): apple ='x' banana = 'y'class Spam (BaseModel): foo: Foo bars: list [Bar] 3, GenericModel General Model (generic):

Use an instance of typing.TypeVar as a parameter, pass it to typing.Generic, and then use it in a model that inherits pydantic.generics.GenericModel:

From typing import Generic, TypeVar, Optional, Listfrom pydantic import BaseModel, validator, ValidationErrorfrom pydantic.generics import GenericModelDataT = TypeVar ('DataT') class Error (BaseModel): code: int message: strclass 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 vdata = DataModel (numbers= [1,2,3], people= []) error = Error (code=404) Message='Not found') print (response [data='value'] (data='value')) # > data='value' error=Noneprint (response [str] (data='value'). Dict ()) # > {'data':' value', 'error': None} print (response [data Model] (data=data). Dict ()) "" {' data': {'numbers': [1,2,3],' people': []}, 'error': None " } "" print (response [data Model] (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 dynamic model.

In some cases, the structure of the model is not known until run time. For this reason, pydantic provides a way for create_model to allow dynamic creation of models.

From pydantic import BaseModel, create_modelDynamicFoobarModel = create_model ('DynamicFoobarModel', foo= (str,...), bar=123) 4. Common types

None,type (None) or literal [none] only allow the value of none

Bool Boolean type

Int integer type

Float floating point type

Str string type

Bytes byte type

List allows list,tuple,set,frozenset,deque, or generators, and converts to lists

Tuple allows list,tuple,set,frozenset,deque, or generators, to be converted to tuples

Dict dictionary type

Set allows list,tuple,set,frozenset,deque, or generators, and conversions to collections

Frozenset allows list,tuple,set,frozenset,deque, or generators, and cast to frozen sets

Deque allows list,tuple,set,frozenset,deque, or generator, and cast to double-ended queues

Date types such as date,datetime,time,timedelta of datetime

Deque, Dict, FrozenSet, List, Optional, Sequence, Set, Tuple, Union,Callable,Pattern and other types in typing

FilePath, file path

DirectoryPath directory path

EmailStr email address

NameEmail valid email address or format

PyObject requires a string and loads python objects that can be imported in the dashed path

Color Color Typ

AnyUrl any URL

SecretStr, SecretBytes sensitive information will be formatted as'*'or''.

Json Typ

PaymentCardNumber payment card type

Constraint types, you can use the con* type function to restrict the values of many common types

Conlist

Item_type: Type [T]: type of list item

Min_items: int = None: minimum number of items in the list

Max_items: int = None: maximum number of items in the list

Conset

Item_type: Type [T]: sets the type of project

Min_items: int = None: minimum number of items in the collection

Max_items: int = None: maximum number of items in the collection

Conint

Strict: bool = False: control type enforcement

Gt: int = None: force the integer to be greater than the set value

Ge: int = None: force the integer to be greater than or equal to the set value

Lt: int = None: force the integer to be less than the set value

Le: int = None: force the integer to be less than or equal to the set value

Multiple_of: int = None: forces the integer to be a multiple of the set value

Confloat

Strict: bool = False: control type enforcement

Gt: float = None: force the floating point number to exceed the set value

Ge: float = None: force float to be greater than or equal to the set value

Lt: float = None: force the floating point to be less than the set value

Le: float = None: force float to be less than or equal to the set value

Multiple_of: float = None: forces float to be a multiple of the set value

Condecimal

Gt: Decimal = None: force decimal to be greater than the set value

Ge: Decimal = None: force decimal to be greater than or equal to the set value

Lt: Decimal = None: force decimal to be less than the set value

Le: Decimal = None: force decimal to be less than or equal to the set value

Max_digits: int = None: the maximum number of digits in the decimal point. It does not include zeros before the decimal point or trailing decimal zeros

Decimal_places: int = None: the maximum number of decimal places allowed. It does not include trailing decimal zeros

Multiple_of: Decimal = None: forces the decimal to be a multiple of the set value

Constr

Strip_whitespace: bool = False: delete leading and trailing spaces

To_lower: bool = False: convert all characters to lowercase

Strict: bool = False: control type enforcement

Min_length: int = None: minimum length of the string

Max_length: int = None: the maximum length of the string

Curtail_length: int = None: when the string length exceeds the set value, the string length is reduced to the set value

Regex: str = None: regular expressions to validate strings

Conbytes

Strip_whitespace: bool = False: delete leading and trailing spaces

To_lower: bool = False: convert all characters to lowercase

Min_length: int = None: minimum length of byte string

Max_length: int = None: maximum length of byte string

Strict types, you can use StrictStr,StrictBytes,StrictInt,StrictFloat, and StrictBool types to prevent forced compatibility

5. Verifier

Using the validator decorator, you can implement complex relationships between custom validation and objects.

From pydantic import BaseModel, ValidationError, validatorclass 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 vuser = 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) ""

Some considerations about the validator:

Validators are "class methods", so the first parameter value they receive is the UserModel class, not UserModel

The second parameter is always the field value to be validated, and you can name it as you like

A single validator can be applied to multiple fields by passing multiple field names, or a single validator can be called on all fields by passing special values.

The keyword parameter pre will cause the validator to be called before other validations

Using each_item=True will cause the validator to be applied to a separate value (such as List,Dict,Set, etc.) rather than the entire object

From typing import Listfrom pydantic import BaseModel, ValidationError, validatorclass 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 calledtry: 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 vtry: 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)"

The keyword parameter always results in always validating, and for performance reasons, the validator is not invoked for the field by default when no value is provided. However, in some cases, it may be useful or necessary to always call the validator, such as setting dynamic default values.

Allow_reuse can use the same validator on multiple fields / models

From pydantic import BaseModel, validatordef 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) VI. Configuration

If you create a model that inherits from BaseSettings, the model initialization program will try to determine the value of any fields that are not passed as keyword parameters by reading from the environment. (if a matching environment variable is not set, the default value is still used. )

This makes it easy:

Create a clearly defined, type-prompted application configuration class

Automatically read configuration changes from environment variables

Manually override specific settings in the initialization program where needed (for example, in unit tests)

From typing import Setfrom pydantic import (BaseModel, BaseSettings, PyObject, RedisDsn, PostgresDsn, Field,) class SubModel (BaseModel): foo = 'bar' apple = 1class 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':,' domains': set (), 'more_settings': {' foo': 'bar',' apple': 1},} ""

Dotenv files are supported to set variables, and pydantic has two ways to load it:

Class Settings (BaseSettings):... Class Config: env_file = '.env' env_file_encoding = 'utf-8'

Or

Settings=Settings (_ env_file='prod.env',_env_file_encoding='utf-8')

Even if you use a dotenv file, pydantic still reads environment variables, which always take precedence over values loaded from the dotenv file.

Pydantic supports setting sensitive information files, and there are also two ways to load them:

Class Settings (BaseSettings):... Database_password: str class Config: secrets_dir ='/ var/run'

Or:

Settings = Settings (_ secrets_dir='/var/run')

Even if you use the secrets directory, pydantic still reads the environment variables from the dotenv file or environment, and the dotenv file and environment variables always take precedence over values loaded from the secrets directory.

7. Use with mypy

Pydantic comes with a mypy plug-in that adds many important pydantic-specific features to mypy to improve its ability to type check code.

For example, the following script:

From datetime import datetimefrom typing import List, Optionalfrom pydantic import BaseModel, NoneStrclass 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, baked 3']) print (m.middle_name) # not a model fieldwork Model () # will raise a validation error for age and list_of_ints

Without any special configuration, mypy catches one of the errors:

13: error: "Model" has no attribute "middle_name"

When the plug-in is enabled, it also captures:

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"

To enable the plug-in, simply add pydantic.mypy to the plug-in list in the mypy configuration file:

[mypy] plugins = pydantic.mypy

To change the value of the plug-in settings, create a section called [pydantic-mypy] in the mypy configuration file and add key-value pairs to the settings you want to override:

[mypy] plugins = pydantic.mypyfollow_imports = silentwarn_redundant_casts = Truewarn_unused_ignores = Truedisallow_any_generics = Truecheck_untyped_defs = Trueno_implicit_reexport = True# for strict mypy: (this is the tricky one: -) disallow_untyped_defs = True [pydantic-mypy] init_forbid_extra = Trueinit_typed = Truewarn_required_dynamic_aliases = Truewarn_untyped_fields = True Thank you for reading this article carefully I hope the article "how to use pydantic in python Library" shared by the editor will be helpful to you. At the same time, I also hope that you will support us and pay attention to the industry information channel. More related knowledge is waiting for you to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report