python LogoPydantic

Pydantic is a Python library for data validation and settings management using Python type hints. It allows developers to define the shape of their data using standard Python type annotations, and then provides runtime validation to ensure that the data conforms to the specified types. If data doesn't match the schema, Pydantic raises clear and informative validation errors.

Key features and benefits include:
- Data Validation and Parsing: Automatically validates data when an instance of a Pydantic model is created. It can parse data from various sources (JSON, dicts) into Python objects.
- Type Hint Integration: Leverages Python's standard type hints (`typing` module) for defining data schemas, making models readable and compatible with linters and IDEs.
- Runtime Validation: Validation happens at runtime, catching data inconsistencies early.
- Serialization and Deserialization: Easily serialize Pydantic models to JSON or dictionaries and deserialize them back into model instances.
- Settings Management: Provides `BaseSettings` for managing application settings, allowing them to be loaded from environment variables or `.env` files with validation.
- Automatic Documentation: Pydantic models can be automatically converted to JSON Schema, which is useful for API documentation (e.g., FastAPI uses Pydantic extensively for this).
- Extensibility: Supports custom validators and data types.
- Performance: Written in Rust for core parsing and validation logic (via `pydantic-core`), making it quite fast.

In essence, Pydantic makes it easier to work with structured data by enforcing data integrity, reducing boilerplate code for validation, and improving code readability through explicit type definitions. It's widely used in web frameworks like FastAPI and for general-purpose data handling.

Example Code

from pydantic import BaseModel, ValidationError, Field
from typing import List, Optional

 1. Define a Pydantic Model
class User(BaseModel):
    id: int = Field(..., gt=0, description="The user's unique identifier, must be positive")
    name: str = Field(..., min_length=2, max_length=50, description="The user's name")
    email: Optional[str] = Field(None, pattern=r"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$", description="The user's email address (optional)")
    is_active: bool = True
    tags: List[str] = Field([], description="A list of tags associated with the user")

 2. Instantiate models with valid data
print("--- Valid Data Examples ---")
try:
    user1 = User(id=1, name="Alice Smith", email="alice@example.com")
    print(f"User 1: {user1.model_dump_json(indent=2)}")  .model_dump_json() serializes to JSON

    user2 = User(id=2, name="Bob Johnson", is_active=False, tags=["admin", "tester"])
    print(f"User 2: {user2.model_dump_json(indent=2)}")

     Accessing attributes
    print(f"User 1's name: {user1.name}")
    print(f"User 2's tags: {user2.tags}")

except ValidationError as e:
    print(f"Unexpected validation error for valid data: {e}")

 3. Instantiate models with invalid data
print("\n--- Invalid Data Examples ---")
 Example 1: Missing required field 'id'
try:
    User(name="Charlie")
except ValidationError as e:
    print(f"Error for missing 'id': {e.errors()}")

 Example 2: Invalid type for 'id' (string instead of int)
try:
    User(id="invalid", name="David")
except ValidationError as e:
    print(f"Error for invalid 'id' type: {e.errors()}")

 Example 3: 'id' not greater than 0
try:
    User(id=0, name="Eve")
except ValidationError as e:
    print(f"Error for 'id' not positive: {e.errors()}")

 Example 4: 'name' too short and 'email' invalid format
try:
    User(id=4, name="J", email="invalid-email")
except ValidationError as e:
    print(f"Error for short name and invalid email: {e.errors()}")

 4. Demonstrate using from_attributes (formerly from_orm)
print("\n--- From Attributes Example ---")
class UserDB:  A mock ORM object or similar
    def __init__(self, id, name, email):
        self.id = id
        self.name = name
        self.email = email

    def __getitem__(self, key):  Pydantic can also read from dictionary-like objects
        return getattr(self, key)

db_user_data = UserDB(id=5, name="Frank", email="frank@example.com")
user_from_db = User.model_validate(db_user_data)  Use .model_validate() for objects or dicts
print(f"User from DB: {user_from_db.model_dump_json(indent=2)}")

 Example using dictionary
dict_user_data = {"id": 6, "name": "Grace", "email": "grace@example.com", "is_active": False}
user_from_dict = User.model_validate(dict_user_data)
print(f"User from Dict: {user_from_dict.model_dump_json(indent=2)}")