07 — Getting Started with Pydantic

Setup
Python
Pydantic
Learn Pydantic basics: define typed data models, validate inputs, and catch configuration errors early in your computer-vision projects.

What is Pydantic?

Pydantic is a Python library for data validation and settings management, built on top of standard Python type hints. You describe the shape of your data once as a class, and Pydantic parses and validates any input against it — raising a clear, specific error the moment something does not match, instead of letting a bad value quietly propagate into your code.

Pydantic is used throughout modern Python tooling, including FastAPI, most LLM structured-output libraries, and countless configuration systems.

Note

Why this matters for computer vision: camera settings, dataset annotation files, and lab-parameter files are all just structured data. Validating them with Pydantic catches a typo'd resolution or a missing field before a long capture or training run starts, not halfway through it.

1. Install Pydantic

With your course virtual environment activated:

pip install pydantic

Check the installed version:

python3 -c "import pydantic; print(pydantic.VERSION)"

This tutorial uses Pydantic v2, the current major version.

2. Define Your First Model

A Pydantic model is a class that inherits from BaseModel, with each field written as a type-annotated attribute:

from pydantic import BaseModel

class CameraConfig(BaseModel):
    name: str
    width: int
    height: int
    fps: float

Create an instance by passing keyword arguments:

cam = CameraConfig(name="pi_camera", width=1280, height=720, fps=30.0)
print(cam)
name='pi_camera' width=1280 height=720 fps=30.0

3. Validation in Action

Pydantic coerces compatible values to the declared type. A numeric string is parsed into an int automatically:

cam = CameraConfig(name="pi_camera", width="1280", height=720, fps=30.0)
print(type(cam.width))
<class 'int'>

But a value that cannot be converted raises a ValidationError that points at the exact field:

CameraConfig(name="pi_camera", width="not-a-number", height=720, fps=30.0)
pydantic_core._pydantic_core.ValidationError: 1 validation error for CameraConfig
width
  Input should be a valid integer, unable to parse string as an integer [type=int_parsing, input_value='not-a-number', input_type=str]

4. Optional Fields & Defaults

Give a field a default value to make it optional, and use Optional[...] when the field may legitimately be None:

from typing import Optional
from pydantic import BaseModel

class CameraConfig(BaseModel):
    name: str
    width: int = 1280
    height: int = 720
    fps: float = 30.0
    device: Optional[str] = None

Now a model can be created with just the required field:

cam = CameraConfig(name="pi_camera")

5. Nested Models

Models can contain other models. Pydantic validates nested data recursively, including when it is passed as a plain dictionary:

class ROI(BaseModel):
    x: int
    y: int
    width: int
    height: int

class CameraConfig(BaseModel):
    name: str
    roi: Optional[ROI] = None

cam = CameraConfig(name="pi_camera", roi={"x": 0, "y": 0, "width": 640, "height": 480})
print(cam.roi.width)

6. Custom Validators

Type checking alone cannot express rules such as "must be positive." Use field_validator for that:

from pydantic import BaseModel, field_validator

class CameraConfig(BaseModel):
    width: int
    height: int

    @field_validator("width", "height")
    @classmethod
    def must_be_positive(cls, v):
        if v <= 0:
            raise ValueError("must be a positive integer")
        return v

Now CameraConfig(width=0, height=480) raises a ValidationError with your custom message instead of silently accepting a useless resolution.

7. Converting To/From JSON

Every model can serialize itself to a Python dict or a JSON string:

cam = CameraConfig(name="pi_camera", width=1280, height=720, fps=30.0)
print(cam.model_dump())
print(cam.model_dump_json())

And parse a model back out of a JSON config file:

import json

with open("camera_config.json") as f:
    cam = CameraConfig(**json.load(f))
Note

model_dump() and model_dump_json() are the Pydantic v2 methods used in this tutorial. If you see .dict() or .json() in older examples online, that is the deprecated Pydantic v1 API.

Good Habits

  • Use a Pydantic model for any config file, lab-parameter file, or API payload — not just function arguments
  • Prefer specific types (int, float, Literal[...]) over Any so mistakes get caught, not passed through
  • Let ValidationError surface and stop the program rather than catching and silently ignoring it
  • Validate data as close as possible to where it enters your program — e.g. a single load_config() function

Next Steps

Use a Pydantic model to validate the configuration file for your next lab (camera settings, ROI, or detection thresholds) before wiring it into your capture or inference script.