pydantic==2.12.5 核心库的功能/用法,以及配套的 pydantic-settings 库的作用,我会从核心功能、核心用法、pydantic-settings 专属用法三部分讲解,贴合 2.12.5 最新版特性,同时兼顾新手易理解性。
一、pydantic==2.12.5 核心功能
Pydantic 是 Python 中强类型数据验证与解析的主流库,2.x 版本相比 1.x 重写了核心代码,性能提升 5-10 倍,同时保留了易用性,核心能力包括:
- 数据验证:基于Python类型注解,自动校验输入数据的类型、范围、格式等,不符合规则则抛出清晰的异常;
- 数据解析/转换:自动将非标准输入(如字符串转数字、json字符串转字典)转换为注解指定的类型,无需手动处理;
- 数据建模 :通过定义
BaseModel模型类,实现结构化数据的统一管理(类似ORM模型,但专注于数据校验而非数据库); - 支持复杂类型 :原生支持列表、字典、嵌套模型、枚举、Union、Optional等Python内置类型,以及Pydantic自定义类型(如
EmailStr、UrlStr); - 灵活的配置:支持字段默认值、可选字段、必选字段、自定义校验规则、别名等;
- 序列化/反序列化:轻松将模型转换为字典、JSON,或从字典/JSON实例化模型,适配API开发、配置解析等场景。
简单来说:Pydantic 让你用「类型注解」快速定义「结构化数据规则」,自动完成「校验+转换+建模」,告别手动写大量if判断的校验代码。
二、pydantic==2.12.5 基本用法
前置准备
先安装核心库(2.12.5 版本):
bash
pip install pydantic==2.12.5
核心基类:BaseModel
所有Pydantic数据模型都继承自 pydantic.BaseModel,通过类型注解定义字段规则,核心用法分「模型定义、实例化、数据操作、校验规则」四部分。
1. 基础模型定义与实例化
最核心的用法,定义模型后实例化,自动完成校验和转换:
python
from pydantic import BaseModel, Field
from typing import Optional, List
# 定义数据模型(继承BaseModel)
class User(BaseModel):
# 必选字段:str类型
name: str
# 必选字段:int类型,自动转换(如输入字符串"20"会转成20)
age: int
# 可选字段:None | List[str],默认值None
hobbies: Optional[List[str]] = None
# 带字段配置的字段:默认值0,别名"phone_num"(适配外部数据的键名),描述用于文档
phone: int = Field(default=0, alias="phone_num", description="用户手机号")
# 1. 正常实例化(符合规则)
user1 = User(name="张三", age=20, hobbies=["篮球", "游戏"], phone_num=13800138000)
print(user1.name) # 张三
print(user1.phone) # 13800138000(自动映射别名)
print(user1.hobbies) # ['篮球', '游戏']
# 2. 自动类型转换(输入字符串age,转成int)
user2 = User(name="李四", age="25", phone_num="13900139000") # 字符串"25"→25,"13900139000"→int
print(type(user2.age)) # <class 'int'>
print(type(user2.phone)) # <class 'int'>
# 3. 校验失败(抛出清晰异常)→ age传非数字、必选字段缺失都会报错
# user3 = User(name="王五", age="二十") # 报错:Input should be a valid integer, got a string
2. 模型的核心数据操作
Pydantic模型提供了便捷的方法,实现模型↔字典/JSON的转换,适配API、配置等场景:
python
# 接上面的User模型,实例化user1
user1 = User(name="张三", age=20, hobbies=["篮球", "游戏"], phone_num=13800138000)
# 1. 转字典:model_dump()(2.x 替代1.x的dict())
print(user1.model_dump())
# 输出:{'name': '张三', 'age': 20, 'hobbies': ['篮球', '游戏'], 'phone': 13800138000}
# 2. 转JSON字符串:model_dump_json()
print(user1.model_dump_json(indent=2)) # indent=2 格式化输出
# 输出:
# {
# "name": "张三",
# "age": 20,
# "hobbies": ["篮球", "游戏"],
# "phone": 13800138000
# }
# 3. 从字典实例化模型(直接传参,或用model_validate())
user_dict = {"name": "赵六", "age": 30, "phone_num": 13700137000}
user4 = User.model_validate(user_dict) # 等价于 User(**user_dict)
print(user4.name) # 赵六
# 4. 从JSON字符串实例化:model_validate_json()
user_json = '{"name": "孙七", "age": 28, "phone_num": 13600136000}'
user5 = User.model_validate_json(user_json)
print(user5.age) # 28
3. 常用校验规则(字段约束/自定义校验)
Pydantic 提供了内置约束 (通过Field)和自定义校验器 ,满足复杂的业务校验需求,2.x 推荐用@field_validator装饰器做字段校验。
(1)内置约束(Field 常用参数)
通过Field设置字段的范围、长度、正则等,无需手写校验:
python
from pydantic import BaseModel, Field
from typing import Annotated
# 常用Field参数:gt(大于)、ge(大于等于)、lt(小于)、le(小于等于)、min_length、max_length、pattern(正则)
class Product(BaseModel):
# 商品名:至少2个字符,最多20个字符
name: str = Field(min_length=2, max_length=20)
# 价格:大于0的浮点数
price: float = Field(gt=0, description="商品价格,必须大于0")
# 手机号:正则匹配中国大陆手机号
phone: str = Field(pattern=r"^1[3-9]\d{9}$")
# 正常实例化
p1 = Product(name="苹果15", price=5999.99, phone="13800138000")
# 校验失败:价格≤0、手机号格式错误、商品名长度不够
# p2 = Product(name="果", price=-100, phone="123456") # 抛出多个异常,清晰提示
(2)自定义字段校验器(@field_validator)
处理内置约束无法满足的个性化校验,比如「年龄必须是成年人(≥18)」「密码必须包含字母和数字」:
python
from pydantic import BaseModel, Field, field_validator
from typing import Optional
class User(BaseModel):
name: str
age: int = Field(ge=0)
password: str
# 自定义校验器:校验age必须≥18(成年人)
# mode="after":表示在校验器执行前,Pydantic已完成基础类型校验(如age是int)
@field_validator("age", mode="after")
def check_adult(cls, v):
if v < 18:
raise ValueError("年龄必须是成年人(≥18岁)")
return v
# 自定义校验器:校验密码必须包含字母和数字,长度≥6
@field_validator("password")
def check_password(cls, v):
if len(v) < 6:
raise ValueError("密码长度必须≥6")
if not (any(c.isalpha() for c in v) and any(c.isdigit() for c in v)):
raise ValueError("密码必须同时包含字母和数字")
return v
# 正常实例化
user1 = User(name="张三", age=20, password="Abc123456")
# 校验失败
# user2 = User(name="李四", age=17, password="123456") # 报错:年龄必须是成年人(≥18岁)
# user3 = User(name="王五", age=25, password="abcdef") # 报错:密码必须同时包含字母和数字
4. 嵌套模型(复杂结构化数据)
支持模型嵌套模型,实现多层级数据的校验,比如「用户模型包含地址模型」:
python
from pydantic import BaseModel
from typing import Optional
# 子模型:地址
class Address(BaseModel):
province: str
city: str
detail: Optional[str] = None # 详细地址,可选
# 父模型:用户(包含地址模型)
class User(BaseModel):
name: str
age: int
address: Address # 嵌套Address模型,必选
# 实例化:嵌套传参(字典形式)
user1 = User(
name="张三",
age=20,
address={"province": "广东省", "city": "深圳市", "detail": "南山区科技园"}
)
# 访问嵌套字段
print(user1.address.province) # 广东省
print(user1.address.detail) # 南山区科技园
# 校验失败:嵌套字段缺失
# user2 = User(name="李四", age=25, address={"province": "北京市"}) # 报错:Address缺少city字段
三、pydantic-settings 功能与基本用法
pydantic-settings 是 Pydantic 官方推出的配置管理库 ,基于 Pydantic 核心的校验能力,专门用于从多源读取配置、统一管理项目配置 ,解决了Python传统配置(如os.getenv)的痛点:
- 手动转换环境变量类型(环境变量默认都是字符串,需手动转int/bool);
- 配置分散(环境变量、配置文件、命令行参数),难以统一管理;
- 无校验,配置错误只有运行时才会发现。
核心功能
- 自动从环境变量、.env文件、配置类默认值读取配置,支持多源优先级(环境变量 > .env文件 > 默认值);
- 基于Pydantic类型注解,自动校验+转换配置值(如字符串"True"转bool,"8000"转int);
- 支持配置嵌套、自定义配置源(如YAML/JSON配置文件);
- 与Pydantic核心库无缝兼容,语法一致。
前置准备
安装 pydantic-settings(与pydantic 2.x 配套,无需指定版本,会自动适配):
bash
pip install pydantic-settings
核心基类:BaseSettings
所有Pydantic配置模型都继承自 pydantic_settings.BaseSettings,语法与Pydantic的BaseModel完全一致,核心差异是「自动读取多源配置」。
1. 基础配置定义(读取环境变量/.env文件)
步骤1:定义配置模型(继承BaseSettings)
python
# settings.py
from pydantic_settings import BaseSettings
from pydantic import Field
from typing import Optional
# 项目配置模型(继承BaseSettings)
class Settings(BaseSettings):
# 服务配置
API_HOST: str = Field(default="127.0.0.1", description="API服务地址")
API_PORT: int = Field(default=8000, description="API服务端口")
# 调试模式:环境变量传"True"/"true"/"1"会自动转bool,"False"/"0"转False
DEBUG: bool = Field(default=False, description="调试模式")
# 数据库配置
DB_URL: str = Field(default="sqlite:///./db.sqlite3", description="数据库连接地址")
# 可选配置
REDIS_HOST: Optional[str] = Field(default=None, description="Redis地址")
# 【关键配置】指定.env文件路径(默认读取项目根目录的.env文件,可自定义)
class Config:
env_file = ".env" # 读取.env文件的环境变量
env_file_encoding = "utf-8" # .env文件编码
# 实例化配置(全局单例,项目中其他地方直接导入即可)
settings = Settings()
# 测试:打印配置
if __name__ == "__main__":
print(f"API地址:{settings.API_HOST}:{settings.API_PORT}")
print(f"调试模式:{settings.DEBUG}")
print(f"数据库地址:{settings.DB_URL}")
步骤2:创建.env文件(项目根目录)
.env 文件是键值对格式的配置文件,Pydantic-settings 会自动读取其中的配置,键名与模型字段名一致:
ini
# .env 文件(项目根目录)
API_HOST=0.0.0.0
API_PORT=8080
DEBUG=True
DB_URL=mysql+pymysql://root:123456@localhost:3306/test
REDIS_HOST=127.0.0.1
步骤3:运行测试
直接运行settings.py,会自动读取.env文件的配置,并完成类型转换:
bash
python settings.py
输出结果:
API地址:0.0.0.0:8080
调试模式:True
数据库地址:mysql+pymysql://root:123456@localhost:3306/test
2. 多源配置的优先级
Pydantic-settings 读取配置的优先级从高到低 :
运行时手动传参 > 系统环境变量 > .env文件配置 > 模型默认值
举个例子:
- 系统环境变量设置
API_PORT=9000; - .env文件设置
API_PORT=8080; - 模型默认值
API_PORT=8000;
运行后settings.API_PORT的值是9000(系统环境变量优先级更高)。
如何设置系统环境变量:
- Linux/Mac 终端:
export API_PORT=9000 && python settings.py - Windows CMD:
set API_PORT=9000 && python settings.py - Windows PowerShell:
$env:API_PORT=9000; python settings.py
3. 配置的使用(项目全局导入)
项目中其他模块直接导入settings实例即可使用配置,无需重复定义,实现配置统一管理:
python
# main.py
from settings import settings
import uvicorn
from fastapi import FastAPI
app = FastAPI(debug=settings.DEBUG)
@app.get("/")
def root():
return {"message": "Hello Pydantic", "port": settings.API_PORT}
if __name__ == "__main__":
uvicorn.run(app, host=settings.API_HOST, port=settings.API_PORT)
4. 嵌套配置模型(复杂配置)
与Pydantic的BaseModel一样,BaseSettings也支持嵌套,适合将不同模块的配置拆分(如数据库、Redis、日志):
python
from pydantic_settings import BaseSettings
from pydantic import Field
# 数据库子配置
class DBConfig(BaseSettings):
url: str = Field(default="sqlite:///./db.sqlite3")
pool_size: int = Field(default=10)
echo: bool = Field(default=False) # 是否打印SQL语句
# Redis子配置
class RedisConfig(BaseSettings):
host: str = Field(default="127.0.0.1")
port: int = Field(default=6379)
db: int = Field(default=0)
# 全局主配置(嵌套子配置)
class Settings(BaseSettings):
api_host: str = Field(default="127.0.0.1")
api_port: int = Field(default=8000)
debug: bool = Field(default=False)
db: DBConfig = DBConfig() # 嵌套数据库配置
redis: RedisConfig = RedisConfig() # 嵌套Redis配置
model_config = SettingsConfigDict(
env_file=".env", # 读取项目根目录的.env文件
env_file_encoding="utf-8",
case_sensitive=False # 环境变量大小写不敏感(DB_HOST和db_host都生效)
)
# 实例化
settings = Settings()
# 访问嵌套配置
print(settings.db.url)
print(settings.redis.port)
对应的.env文件可通过点语法设置嵌套配置:
ini
api_host=0.0.0.0
api_port=8080
debug=True
# 嵌套数据库配置(点语法)
db.url=mysql+pymysql://root:123456@localhost:3306/test
db.pool_size=20
db.echo=True
# 嵌套Redis配置
redis.host=192.168.1.100
redis.port=6379
redis.db=1
四、pydantic vs pydantic-settings 核心区别
| 库 | 核心基类 | 核心用途 | 关键特性 |
|---|---|---|---|
| pydantic==2.12.5 | BaseModel | 通用数据校验、建模、解析 | 类型注解校验、自动转换、序列化 |
| pydantic-settings | BaseSettings | 项目配置管理(多源读取) | 继承BaseModel能力+自动读环境变量/.env |
核心关联 :BaseSettings 是 BaseModel 的子类,因此pydantic的所有用法(Field、校验器、嵌套、序列化)在pydantic-settings中都能直接使用,只是增加了「配置源读取」的能力。
五、2.x 版本关键注意点(避坑)
你使用的是pydantic 2.12.5,相比1.x有部分API废弃/更名,新手需注意:
- 转字典用
model_dump()替代 1.x 的dict(); - 转JSON用
model_dump_json()替代 1.x 的json(); - 从字典校验实例化用
model_validate()替代 1.x 的parse_obj(); - 从JSON校验实例化用
model_validate_json()替代 1.x 的parse_raw(); - 字段校验器用
@field_validator替代 1.x 的@validator,且新增mode参数; - 全局配置从模型的
Config类设置(如env_file、alias_generator),语法不变。
总结
- pydantic==2.12.5 是Python强类型数据校验的核心库,通过
BaseModel+类型注解,实现数据建模、自动校验、类型转换、序列化,告别手动校验代码,是API开发、数据处理的必备工具; - pydantic-settings 是Pydantic官方的配置管理库,基于
BaseSettings(BaseModel子类),在Pydantic核心能力基础上,增加了从环境变量/.env文件自动读取配置的能力,解决了Python配置管理的痛点; - 两者语法高度一致,
pydantic-settings完全继承pydantic的所有特性(嵌套、校验器、Field等),仅新增配置源相关能力; - 项目中常用搭配:pydantic 做接口参数/数据校验 ,pydantic-settings 做项目全局配置管理(如数据库、服务端口、环境变量)。