Rumah > Artikel > pembangunan bahagian belakang > Amalan Terbaik untuk Menggunakan Pydantic dalam Python
Pydantic ialah perpustakaan Python yang memudahkan pengesahan data menggunakan pembayang jenis. Ia memastikan integriti data dan menawarkan cara mudah untuk mencipta model data dengan semakan dan pengesahan jenis automatik.
Dalam aplikasi perisian, pengesahan data yang boleh dipercayai adalah penting untuk mengelakkan ralat, isu keselamatan dan tingkah laku yang tidak dapat diramalkan.
Panduan ini menyediakan amalan terbaik untuk menggunakan Pydantic dalam projek Python, meliputi definisi model, pengesahan data, pengendalian ralat dan pengoptimuman prestasi.
Untuk memasang Pydantic, gunakan pip, pemasang pakej Python, dengan arahan:
pip install pydantic
Arahan ini memasang Pydantic dan kebergantungannya.
Buat model Pydantic dengan membuat kelas yang diwarisi daripada BaseModel. Gunakan anotasi jenis Python untuk menentukan jenis setiap medan:
from pydantic import BaseModel class User(BaseModel): id: int name: str email: str
Pydantic menyokong pelbagai jenis medan, termasuk int, str, float, bool, list dan dict. Anda juga boleh menentukan model bersarang dan jenis tersuai:
from typing import List, Optional from pydantic import BaseModel class Address(BaseModel): street: str city: str zip_code: Optional[str] = None class User(BaseModel): id: int name: str email: str age: Optional[int] = None addresses: List[Address]
Setelah anda menentukan model Pydantic, buat kejadian dengan menyediakan data yang diperlukan. Pydantic akan mengesahkan data dan menimbulkan ralat jika mana-mana medan tidak memenuhi keperluan yang ditentukan:
user = User( id=1, name="John Doe", email="john.doe@example.com", addresses=[{"street": "123 Main St", "city": "Anytown", "zip_code": "12345"}] ) print(user) # Output: # id=1 name='John Doe' email='john.doe@example.com' age=None addresses=[Address(street='123 Main St', city='Anytown', zip_code='12345')]
Model Pydantic menggunakan anotasi jenis Python untuk menentukan jenis medan data.
Mereka menyokong pelbagai jenis terbina dalam, termasuk:
Contoh:
from typing import List, Dict, Optional, Union from pydantic import BaseModel class Item(BaseModel): name: str price: float tags: List[str] metadata: Dict[str, Union[str, int, float]] class Order(BaseModel): order_id: int items: List[Item] discount: Optional[float] = None
Selain jenis terbina dalam, anda boleh mentakrifkan jenis tersuai menggunakan conint Pydantic, constr dan fungsi kekangan lain.
Ini membolehkan anda menambah peraturan pengesahan tambahan, seperti kekangan panjang pada rentetan atau julat nilai untuk integer.
Contoh:
from pydantic import BaseModel, conint, constr class Product(BaseModel): name: constr(min_length=2, max_length=50) quantity: conint(gt=0, le=1000) price: float product = Product(name="Laptop", quantity=5, price=999.99)
Secara lalai, medan dalam model Pydantic diperlukan melainkan ditandakan secara eksplisit sebagai pilihan.
Jika medan yang diperlukan tiada semasa instansiasi model, Pydantic akan menimbulkan Ralat Pengesahan.
Contoh:
from pydantic import BaseModel class User(BaseModel): id: int name: str email: str user = User(id=1, name="John Doe") # Output # Field required [type=missing, input_value={'id': 1, 'name': 'John Doe'}, input_type=dict]
Medan boleh dijadikan pilihan dengan menggunakan Pilihan daripada modul menaip dan memberikan nilai lalai.
Contoh:
from pydantic import BaseModel from typing import Optional class User(BaseModel): id: int name: str email: Optional[str] = None user = User(id=1, name="John Doe")
Dalam contoh ini, e-mel adalah pilihan dan lalai kepada Tiada jika tidak disediakan.
Pydantic membenarkan model bersarang antara satu sama lain, membolehkan struktur data yang kompleks.
Model bersarang ditakrifkan sebagai medan model lain, memastikan integriti dan pengesahan data pada berbilang peringkat.
Contoh:
from pydantic import BaseModel from typing import Optional, List class Address(BaseModel): street: str city: str zip_code: Optional[str] = None class User(BaseModel): id: int name: str email: str addresses: List[Address] user = User( id=1, name="John Doe", email="john.doe@example.com", addresses=[{"street": "123 Main St", "city": "Anytown"}] )
Apabila bekerja dengan model bersarang, adalah penting untuk:
Pydantic termasuk satu set pengesah terbina dalam yang mengendalikan tugas pengesahan data biasa secara automatik.
Pengesah ini termasuk:
Pengesah ini memudahkan proses memastikan integriti dan pematuhan data dalam model anda.
Berikut ialah beberapa contoh yang menunjukkan pengesah terbina dalam:
daripada import pydantic BaseModel, EmailStr, conint, constr
class User(BaseModel): id: conint(gt=0) # id must be greater than 0 name: constr(min_length=2, max_length=50) # name must be between 2 and 50 characters email: EmailStr # email must be a valid email address age: conint(ge=18) # age must be 18 or older user = User(id=1, name="John Doe", email="john.doe@example.com", age=25)
Dalam contoh ini, model Pengguna menggunakan pengesah terbina dalam untuk memastikan id lebih besar daripada 0, nama antara 2 dan 50 aksara, e-mel ialah alamat e-mel yang sah dan umur 18 tahun ke atas.
Untuk dapat menggunakan pengesah e-mel, anda perlu memasang sambungan kepada pydantic:
pip install pydantic[email]
Pydantic allows you to define custom validators for more complex validation logic.
Custom validators are defined using the @field_validator decorator within your model class.
Example of a custom validator:
from pydantic import BaseModel, field_validator class Product(BaseModel): name: str price: float @field_validator('price') def price_must_be_positive(cls, value): if value <= 0: raise ValueError('Price must be positive') return value product = Product(name="Laptop", price=999.99)
Here, the price_must_be_positive validator ensures that the price field is a positive number.
Custom validators are registered automatically when you define them within a model using the @field_validator decorator. Validators can be applied to individual fields or across multiple fields.
Example of registering a validator for multiple fields:
from pydantic import BaseModel, field_validator class Person(BaseModel): first_name: str last_name: str @field_validator('first_name', 'last_name') def names_cannot_be_empty(cls, value): if not value: raise ValueError('Name fields cannot be empty') return value person = Person(first_name="John", last_name="Doe")
In this example, the names_cannot_be_empty validator ensures that both the first_name and last_name fields are not empty.
Pydantic models can be customized using an inner Config class.
This class allows you to set various configuration options that affect the model's behavior, such as validation rules, JSON serialization, and more.
Example of a Config class:
from pydantic import BaseModel class User(BaseModel): id: int name: str email: str class Config: str_strip_whitespace = True # Strip whitespace from strings str_min_length = 1 # Minimum length for any string field user = User(id=1, name=" John Doe ", email="john.doe@example.com") print(user) # Output: # id=1 name='John Doe' email='john.doe@example.com'
In this example, the Config class is used to strip whitespace from string fields and enforce a minimum length of 1 for any string field.
Some common configuration options in Pydantic's Config class include:
When Pydantic finds data that doesn't conform to the model's schema, it raises a ValidationError.
This error provides detailed information about the issue, including the field name, the incorrect value, and a description of the problem.
Here's an example of how default error messages are structured:
from pydantic import BaseModel, ValidationError, EmailStr class User(BaseModel): id: int name: str email: EmailStr try: user = User(id='one', name='John Doe', email='invalid-email') except ValidationError as e: print(e.json()) # Output: # [{"type":"int_parsing","loc":["id"],"msg":"Input should be a valid integer, unable to parse string as an integer","input":"one","url":"https://errors.pydantic.dev/2.8/v/int_parsing"},{"type":"value_error","loc":["email"],"msg":"value is not a valid email address: An email address must have an @-sign.","input":"invalid-email","ctx":{"reason":"An email address must have an @-sign."},"url":"https://errors.pydantic.dev/2.8/v/value_error"}]
In this example, the error message will indicate that id must be an integer and email must be a valid email address.
Pydantic allows you to customize error messages for specific fields by raising exceptions with custom messages in validators or by setting custom configurations.
Here’s an example of customizing error messages:
from pydantic import BaseModel, ValidationError, field_validator class Product(BaseModel): name: str price: float @field_validator('price') def price_must_be_positive(cls, value): if value <= 0: raise ValueError('Price must be a positive number') return value try: product = Product(name='Laptop', price=-1000) except ValidationError as e: print(e.json()) # Output: # [{"type":"value_error","loc":["price"],"msg":"Value error, Price must be a positive number","input":-1000,"ctx":{"error":"Price must be a positive number"},"url":"https://errors.pydantic.dev/2.8/v/value_error"}]
In this example, the error message for price is customized to indicate that it must be a positive number.
Effective error reporting involves providing clear, concise, and actionable feedback to users or developers.
Here are some best practices:
Examples of best practices in error reporting:
from pydantic import BaseModel, ValidationError, EmailStr import logging logging.basicConfig(level=logging.INFO) class User(BaseModel): id: int name: str email: EmailStr def create_user(data): try: user = User(**data) return user except ValidationError as e: logging.error("Validation error: %s", e.json()) return {"error": "Invalid data provided", "details": e.errors()} user_data = {'id': 'one', 'name': 'John Doe', 'email': 'invalid-email'} response = create_user(user_data) print(response) # Output: # ERROR:root:Validation error: [{"type":"int_parsing","loc":["id"],"msg":"Input should be a valid integer, unable to parse string as an integer","input":"one","url":"https://errors.pydantic.dev/2.8/v/int_parsing"},{"type":"value_error","loc":["email"],"msg":"value is not a valid email address: An email address must have an @-sign.","input":"invalid-email","ctx":{"reason":"An email address must have an @-sign."},"url":"https://errors.pydantic.dev/2.8/v/value_error"}] # {'error': 'Invalid data provided', 'details': [{'type': 'int_parsing', 'loc': ('id',), 'msg': 'Input should be a valid integer, unable to parse string as an integer', 'input': 'one', 'url': 'https://errors.pydantic.dev/2.8/v/int_parsing'}, {'type': 'value_error', 'loc': ('email',), 'msg': 'value is not a valid email address: An email address must have an @-sign.', 'input': 'invalid-email', 'ctx': {'reason': 'An email address must have an @-sign.'}}]}
In this example, validation errors are logged, and a user-friendly error message is returned, helping maintain application stability and providing useful feedback to the user.
Lazy initialization is a technique that postpones the creation of an object until it is needed.
In Pydantic, this can be useful for models with fields that are costly to compute or fetch. By delaying the initialization of these fields, you can reduce the initial load time and improve performance.
Example of lazy initialization:
from pydantic import BaseModel from functools import lru_cache class DataModel(BaseModel): name: str expensive_computation: str = None @property @lru_cache(maxsize=1) def expensive_computation(self): # Simulate an expensive computation result = "Computed Value" return result data_model = DataModel(name="Test") print(data_model.expensive_computation)
In this example, the expensive_computation field is computed only when accessed for the first time, reducing unnecessary computations during model initialization.
Pydantic models automatically validate data during initialization.
However, if you know that certain data has already been validated or if validation is not necessary in some contexts, you can disable validation to improve performance.
This can be done using the model_construct method, which bypasses validation:
Example of avoiding redundant validation:
from pydantic import BaseModel class User(BaseModel): id: int name: str email: str # Constructing a User instance without validation data = {'id': 1, 'name': 'John Doe', 'email': 'john.doe@example.com'} user = User.model_construct(**data)
In this example, User.model_construct is used to create a User instance without triggering validation, which can be useful in performance-critical sections of your code.
When dealing with large datasets or high-throughput systems, efficiently parsing raw data becomes critical.
Pydantic provides the model_validate_json method, which can be used to parse JSON or other serialized data formats directly into Pydantic models.
Example of efficient data parsing:
from pydantic import BaseModel class User(BaseModel): id: int name: str email: str json_data = '{"id": 1, "name": "John Doe", "email": "john.doe@example.com"}' user = User.model_validate_json(json_data) print(user)
In this example, model_validate_json is used to parse JSON data into a User model directly, providing a more efficient way to handle serialized data.
Pydantic models can be configured to validate data only when necessary.
The validate_default and validate_assignment options in the Config class control when validation occurs, which can help improve performance:
Example configuration:
from pydantic import BaseModel class User(BaseModel): id: int name: str email: str class Config: validate_default = False # Only validate fields set during initialization validate_assignment = True # Validate fields on assignment user = User(id=1, name="John Doe", email="john.doe@example.com") user.email = "new.email@example.com" # This assignment will trigger validation
In this example, validate_default is set to False to avoid unnecessary validation during initialization, and validate_assignment is set to True to ensure that fields are validated when they are updated.
Pydantic's BaseSettings class is designed for managing application settings, supporting environment variable loading and type validation.
This helps in configuring applications for different environments (e.g., development, testing, production).
Consider this .env file:
database_url=db secret_key=sk debug=False
Example of using BaseSettings:
from pydantic_settings import BaseSettings class Settings(BaseSettings): database_url: str secret_key: str debug: bool = False class Config: env_file = ".env" settings = Settings() print(settings.model_dump()) # Output: # {'database_url': 'db', 'secret_key': 'sk', 'debug': False}
In this example, settings are loaded from environment variables, and the Config class specifies that variables can be loaded from a .env file.
For using BaseSettings you will need to install an additional package:
pip install pydantic-settings
Managing settings effectively involves a few best practices:
One common mistake when using Pydantic is misapplying type annotations, which can lead to validation errors or unexpected behavior.
Here are a few typical mistakes and their solutions:
Ignoring performance implications when using Pydantic can lead to slow applications, especially when dealing with large datasets or frequent model instantiations.
Here are some strategies to avoid performance bottlenecks:
Overcomplicating Pydantic models can make them difficult to maintain and understand.
Here are some tips to keep models simple and maintainable:
Dalam panduan ini, kami telah merangkumi pelbagai amalan terbaik untuk menggunakan Pydantic dengan berkesan dalam projek Python anda.
Kami bermula dengan asas untuk bermula dengan Pydantic, termasuk pemasangan, penggunaan asas dan menentukan model. Kami kemudiannya menyelidiki ciri lanjutan seperti jenis tersuai, penyiaran dan penyahsirilan serta pengurusan tetapan.
Pertimbangan prestasi utama, seperti mengoptimumkan permulaan model dan penghuraian data yang cekap, telah diserlahkan untuk memastikan aplikasi anda berjalan lancar.
Kami juga membincangkan masalah biasa, seperti menyalahgunakan anotasi jenis, mengabaikan implikasi prestasi dan model yang terlalu rumit serta menyediakan strategi untuk mengelakkannya.
Menggunakan amalan terbaik ini dalam projek dunia sebenar anda akan membantu anda memanfaatkan kuasa penuh Pydantic, menjadikan kod anda lebih teguh, boleh diselenggara dan berprestasi.
Atas ialah kandungan terperinci Amalan Terbaik untuk Menggunakan Pydantic dalam Python. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!