
使用 Pydantic 從 JSON、JSONL、CSV、TOML、YAML、XML 與 INI 文件中驗證數據【免費下載鏈接】pydanticData validation using Python type hints項目地址: https://gitcode.com/GitHub_Trending/py/pydantic本文是 Pydantic 處理各類文件數據的實戰指南。圍繞倉庫中的 docs/examples/files.md 展開系統講解如何用同一個Person模型從 JSON、JSONL、CSV、TOML、YAML、XML、INI 七種常見文件格式中讀取并驗證數據同時深入model_validate_json、TypeAdapter、model_validate的源碼實現幫助你掌握文件 → 數據 → 強類型模型的完整鏈路并學會在批量數據中精確定位錯誤記錄。讀完本文你將能夠針對任意一種常見文件格式寫出可復制的驗證代碼并理解其背后的校驗機制與參數細節。!!! note 配置文件場景的進階選擇 如果你的目標是用上述文件格式解析配置 / 設置而非業務數據可以考慮使用pydantic-settings庫它為這類數據提供了內置解析支持如.env、.toml等來源。JSON 文件從字符串到模型的model_validate_json.json文件是以人類可讀形式存儲鍵值數據的最常見方式。假設存在如下person.json{ name: John Doe, age: 30, email: johnexample.com }驗證這段數據只需兩步用pathlib讀取文件內容再調用類方法model_validate_jsonimport pathlib from pydantic import BaseModel, EmailStr, PositiveInt class Person(BaseModel): name: str age: PositiveInt email: EmailStr json_string pathlib.Path(person.json).read_text() person Person.model_validate_json(json_string) print(person) # nameJohn Doe age30 emailjohnexample.com這里PositiveInt保證年齡必須為正整數EmailStr要求字段是合法郵箱格式它們在驗證階段共同起作用。驗證失敗ValidationError聚合全部問題如果文件數據不合法Pydantic 會拋出ValidationError。例如以下person.json{ age: -30, email: not-an-email-address }這份數據存在三處問題缺少name字段age為負數email不是合法郵箱地址。Pydantic 會一次性聚合所有錯誤并拋出import pathlib from pydantic import BaseModel, EmailStr, PositiveInt, ValidationError class Person(BaseModel): name: str age: PositiveInt email: EmailStr json_string pathlib.Path(person.json).read_text() try: person Person.model_validate_json(json_string) except ValidationError as err: print(err) 3 validation errors for Person name Field required [typemissing, input_value{age: -30, email: not-an-email-address}, input_typedict] For further information visit https://errors.pydantic.dev/2/v/missing age Input should be greater than 0 [typegreater_than, input_value-30, input_typeint] For further information visit https://errors.pydantic.dev/2/v/greater_than email value is not a valid email address: An email address must have an -sign. [typevalue_error, input_valuenot-an-email-address, input_typestr] 每條錯誤都包含字段位置name/age/email、錯誤類型碼missing、greater_than、value_error、被拒絕的輸入值input_value與輸入類型input_type便于程序化處理。深入源碼model_validate_json的簽名與底層調用model_validate_json定義在 pydantic/main.py其完整簽名如下classmethod def model_validate_json( cls, json_data: str | bytes | bytearray, *, strict: bool | None None, extra: ExtraValues | None None, context: Any | None None, by_alias: bool | None None, by_name: bool | None None, ) - Self:json_dataJSON 數據支持str、bytes、bytearray三種輸入直接對接文件read_bytes()場景strict是否強制嚴格類型校驗覆蓋模型的全局配置extra對額外字段是ignore、allow還是forbid對應ConfigDict.extracontext傳遞給校驗器的額外上下文變量可配合帶info.context的校驗器使用by_alias/by_name是否按字段別名 / 字段名匹配輸入數據二者不能同時為False否則拋出PydanticUserError代碼validate-by-alias-and-name-false。在實現上該方法最終委托給cls.__pydantic_validator__.validate_json(...)pydantic/main.py即 Pydantic 底層用 Rust 實現的pydantic-core校驗器這也是其高性能的來源。倉庫測試 tests/test_main.py 中的test_model_validate_json_strict驗證了strict參數對寬松/嚴格模型的覆蓋行為strictNone時沿用模型配置strictFalse允許字符串1轉為intstrictTrue則要求輸入本身就是整數。批量 JSON 記錄用TypeAdapter驗證list[Person]實際生產中一個.json文件往往包含大量同類數據例如一個人員列表[ { name: John Doe, age: 30, email: johnexample.com }, { name: Jane Doe, age: 25, email: janeexample.com } ]此時應使用TypeAdapter針對list[Person]這個單個類型進行驗證import pathlib from pydantic import BaseModel, EmailStr, PositiveInt, TypeAdapter class Person(BaseModel): name: str age: PositiveInt email: EmailStr person_list_adapter TypeAdapter(list[Person]) # (1)! json_string pathlib.Path(people.json).read_text() people person_list_adapter.validate_json(json_string) print(people) # [Person(nameJohn Doe, age30, emailjohnexample.com), Person(nameJane Doe, age25, emailjaneexample.com)]使用TypeAdapter驗證Person對象列表。TypeAdapter是 Pydantic 中用于針對單一類型執行驗證與序列化的構造為沒有實例方法的類型如原始類型、列表、dataclass 等暴露了BaseModel的一部分能力見 pydantic/type_adapter.py。大文件流水線中的錯誤定位只有兩條記錄時找出壞數據很容易但當流水線處理包含數千條記錄的文件時ValidationError的loc錯誤位置會給出出問題記錄的下標。如果流水線無人值守Logfire 會記錄失敗的驗證及其字段位置和拒絕值使你在運行結束后仍能定位到出問題的記錄。相關的排查細節參見 troubleshooting 文檔。JSON Lines.jsonl文件.jsonl文件是一系列以換行符分隔的 JSON 對象驗證方式與列表 JSON 類似。考慮如下people.jsonl{name: John Doe, age: 30, email: johnexample.com} {name: Jane Doe, age: 25, email: janeexample.com}逐行讀取并調用model_validate_jsonimport pathlib from pydantic import BaseModel, EmailStr, PositiveInt class Person(BaseModel): name: str age: PositiveInt email: EmailStr json_lines pathlib.Path(people.jsonl).read_text().splitlines() people [Person.model_validate_json(line) for line in json_lines] print(people) # [Person(nameJohn Doe, age30, emailjohnexample.com), Person(nameJane Doe, age25, emailjaneexample.com)]相比一次性加載整個 JSON 列表.jsonl的優勢在于可以逐行流式處理面對超大文件時用for line in f遍歷文件對象逐行驗證避免把整個文件讀入內存。此時loc中的下標即對應文件行號從 0 計便于回查源文件。需要說明的是TypeAdapter.validate_json還提供實驗性的experimental_allow_partial參數取值False/off、True/on、trailing-strings可開啟流式分塊輸入的部分驗證partial validation能力詳見 pydantic/type_adapter.py。CSV 文件csv.DictReadermodel_validateCSV 是存儲表格數據最常見的格式之一。Pydantic 本身不解析 CSV而是推薦配合 Python 標準庫csv模塊讀取再交給模型驗證。考慮如下people.csvname,age,email John Doe,30,johnexample.com Jane Doe,25,janeexample.com驗證代碼import csv from pydantic import BaseModel, EmailStr, PositiveInt class Person(BaseModel): name: str age: PositiveInt email: EmailStr with open(people.csv) as f: reader csv.DictReader(f) people [Person.model_validate(row) for row in reader] print(people) # [Person(nameJohn Doe, age30, emailjohnexample.com), Person(nameJane Doe, age25, emailjaneexample.com)]要點csv.DictReader把每一行轉成以表頭為鍵的dict其鍵名與模型字段名一致時可直接model_validate由于age在 CSV 中本質是字符串30PositiveInt在寬松模式下會自動完成字符串到整數的轉換——這正是model_validate走 Python 對象驗證路徑而非 JSON 字符串路徑的典型場景若表頭與字段名不一致可借助字段別名Field(alias...)或先對行做鍵名映射。TOML 文件tomllib解析后驗證TOML 因其簡潔易讀常被用于配置文件。考慮如下person.tomlname John Doe age 30 email johnexample.com驗證代碼tomllib是 Python 3.11 標準庫import tomllib from pydantic import BaseModel, EmailStr, PositiveInt class Person(BaseModel): name: str age: PositiveInt email: EmailStr with open(person.toml, rb) as f: data tomllib.load(f) person Person.model_validate(data) print(person) # nameJohn Doe age30 emailjohnexample.com注意tomllib.load要求以二進制模式rb打開文件這是該 API 的硬性約束。TOML 的嵌套表結構天然對應嵌套模型例如[database]段可映射為嵌套的Database子模型。YAML 文件PyYAMLsafe_load后驗證YAML 是常用于配置文件的、人類可讀的數據序列化格式。考慮如下person.yamlname: John Doe age: 30 email: johnexample.com驗證代碼依賴 PyYAML 庫pip install pyyamlimport yaml from pydantic import BaseModel, EmailStr, PositiveInt class Person(BaseModel): name: str age: PositiveInt email: EmailStr with open(person.yaml) as f: data yaml.safe_load(f) person Person.model_validate(data) print(person) # nameJohn Doe age30 emailjohnexample.com務必使用yaml.safe_load而非yaml.loadsafe_load只解析標準 YAML 標簽避免反序列化任意 Python 對象帶來的安全風險。解析結果同樣是以字符串為主的普通 dictPydantic 的寬松模式會完成后續類型轉換。XML 文件ElementTree提取后驗證XML 是一種既人類可讀又機器可讀的標記語言。考慮如下person.xml?xml version1.0? person nameJohn Doe/name age30/age emailjohnexample.com/email /person使用標準庫xml.etree.ElementTree解析將子標簽名映射為字典鍵后再驗證import xml.etree.ElementTree as ET from pydantic import BaseModel, EmailStr, PositiveInt class Person(BaseModel): name: str age: PositiveInt email: EmailStr tree ET.parse(person.xml).getroot() data {child.tag: child.text for child in tree} person Person.model_validate(data) print(person) # nameJohn Doe age30 emailjohnexample.com這里的核心技巧是{child.tag: child.text for child in tree}把 XML 子元素變成{標簽: 文本}字典從而復用model_validate的對象驗證路徑。更復雜的 XML 結構嵌套元素、屬性可據此擴展為遞歸轉換函數。同時應注意解析不可信的 XML 輸入時需防范 XXE外部實體注入風險可考慮使用禁用外部實體的解析方式。INI 文件configparser節映射后驗證INI 是使用節section與鍵值對的簡單配置文件格式常見于 Windows 應用與較老軟件。考慮如下person.ini[PERSON] name John Doe age 30 email johnexample.com驗證代碼import configparser from pydantic import BaseModel, EmailStr, PositiveInt class Person(BaseModel): name: str age: PositiveInt email: EmailStr config configparser.ConfigParser() config.read(person.ini) person Person.model_validate(config[PERSON]) print(person) # nameJohn Doe age30 emailjohnexample.com關鍵點config[PERSON]返回的是SectionProxy對象它實現了映射接口__getitem__/keys()等因此可以直接傳給model_validate。若配置文件中存在多個節也可以將整個config轉換為普通字典后按需選取對應節進行驗證。七種文件格式速查對照文件格式解析方式標準庫/三方讀取模式驗證入口核心要點JSONpathlib.read_text文本model_validate_json/TypeAdapter.validate_json直接傳 JSON 字符串性能最高JSONL文件逐行 /splitlines文本逐行model_validate_json可流式處理大文件loc對應行號CSVcsv.DictReader文本model_validate表頭作鍵字符串自動轉類型TOMLtomllib.load二進制rbmodel_validate嵌套表對應嵌套模型YAMLyaml.safe_loadPyYAML文本model_validate必須用safe_load防安全風險XMLxml.etree.ElementTree文本model_validate先轉{tag: text}字典INIconfigparser.ConfigParser文本model_validateSectionProxy天然是映射對象實踐小結與驗證閉環本文所有示例均來自倉庫文檔 docs/examples/files.md且這些示例會被倉庫的文檔測試機制tests/test_docs.py 中的pytest_examples驅動執行與斷言因此具備可復現性。在實際項目中建議按以下模式組織文件驗證邏輯用標準庫或輕量三方庫把文件解析為純 Python 對象dict / list用model_validatePython 對象或model_validate_jsonJSON 字符串完成強類型校驗與類型轉換批量場景用TypeAdapter包裹容器類型如list[Person]并在except ValidationError中利用err.errors()的loc定位出錯記錄無人值守流水線可結合 Logfire 與 troubleshooting 方案記錄失敗驗證的完整輸入與位置。這樣無論數據來自哪種文件格式你的業務代碼始終面對的是經過驗證的強類型模型從而把數據是否可信的問題統一收斂到 Pydantic 的驗證層。【免費下載鏈接】pydanticData validation using Python type hints項目地址: https://gitcode.com/GitHub_Trending/py/pydantic創作聲明:本文部分內容由AI輔助生成(AIGC),僅供參考