Was ist mit Standardwerten und Argumentextraktionen?
from pydantic import validate_call@validate_call(validate_return=True)
def add(*args: int, a: int, b: int = 4) -> int:
return str(sum(args) + a + b)
# ----
add(4,3,4)
> ValidationError: 1 validation error for add
a
Lacking required key phrase solely argument (kind=missing_keyword_only_argument, input_value=ArgsKwargs((4, 3, 4)), input_type=ArgsKwargs)
For additional data go to <https://errors.pydantic.dev/2.5/v/missing_keyword_only_argument>
# ----
add(4, 3, 4, a=3)
> 18
# ----
@validate_call
def add(*args: int, a: int, b: int = 4) -> int:
return str(sum(args) + a + b)
# ----
add(4, 3, 4, a=3)
> '18'
Erkenntnisse aus diesem Beispiel:
- Sie können den Typ der variablen Anzahl von Argumentendeklarationen kommentieren (*args).
- Standardwerte sind weiterhin eine Choice, auch wenn Sie variable Datentypen kommentieren.
validate_call
akzeptiertvalidate_return
Argument, das auch die Validierung des Funktionsrückgabewerts vornimmt. In diesem Fall wird auch eine Datentypkonvertierung angewendet.validate_return
ist eingestellt aufFalse
standardmäßig. Wenn es so belassen wird, gibt die Funktion möglicherweise nicht das zurück, was in den Typhinweisen deklariert ist.
Was ist, wenn Sie den Datentyp validieren, aber auch die Werte einschränken möchten, die die Variable annehmen kann? Beispiel:
from pydantic import validate_call, Subject
from typing import Annotated type_age = Annotated(int, Subject(lt=120))
@validate_call(validate_return=True)
def add(age_one: int, age_two: type_age) -> int:
return age_one + age_two
add(3, 300)
> ValidationError: 1 validation error for add
1
Enter ought to be lower than 120 (kind=less_than, input_value=200, input_type=int)
For additional data go to <https://errors.pydantic.dev/2.5/v/less_than>
Dieses Beispiel zeigt:
- Sie können
Annotated
Undpydantic.Subject
um nicht nur den Datentyp zu validieren, sondern auch Metadaten hinzuzufügen, die Pydantic verwendet, um variable Werte und Formate einzuschränken. ValidationError
ist wieder einmal sehr ausführlich darüber, was mit unserem Funktionsaufruf nicht stimmte. Das kann wirklich hilfreich sein.
Hier ist ein weiteres Beispiel, wie Sie Variablenwerte sowohl validieren als auch einschränken können. Wir simulieren eine Nutzlast (ein Wörterbuch), die Sie in Ihrer Funktion verarbeiten möchten, nachdem sie validiert wurde:
from pydantic import HttpUrl, PastDate
from pydantic import Subject
from pydantic import validate_call
from typing import AnnotatedIdentify = Annotated(str, Subject(min_length=2, max_length=15))
@validate_call(validate_return=True)
def process_payload(url: HttpUrl, identify: Identify, birth_date: PastDate) -> str:
return f'{identify=}, {birth_date=}'
# ----
payload = {
'url': 'httpss://instance.com',
'identify': 'J',
'birth_date': '2024-12-12'
}
process_payload(**payload)
> ValidationError: 3 validation errors for process_payload
url
URL scheme ought to be 'http' or 'https' (kind=url_scheme, input_value='httpss://instance.com', input_type=str)
For additional data go to <https://errors.pydantic.dev/2.5/v/url_scheme>
identify
String ought to have at the very least 2 characters (kind=string_too_short, input_value='J', input_type=str)
For additional data go to <https://errors.pydantic.dev/2.5/v/string_too_short>
birth_date
Date ought to be up to now (kind=date_past, input_value='2024-12-12', input_type=str)
For additional data go to <https://errors.pydantic.dev/2.5/v/date_past>
# ----
payload = {
'url': '<https://instance.com>',
'identify': 'Joe-1234567891011121314',
'birth_date': '2020-12-12'
}
process_payload(**payload)
> ValidationError: 1 validation error for process_payload
identify
String ought to have at most 15 characters (kind=string_too_long, input_value='Joe-1234567891011121314', input_type=str)
For additional data go to <https://errors.pydantic.dev/2.5/v/string_too_long>
Dies waren die Grundlagen zur Validierung von Funktionsargumenten und deren Rückgabewerten.
Nun kommen wir zur zweitwichtigsten Möglichkeit, Pydantic zur Validierung und Verarbeitung von Daten zu verwenden: durch die Definition von Modellen.
Wie Sie sehen werden, ist dieser Teil für die Zwecke der Datenverarbeitung interessanter.
Bisher haben wir validate_call
um Funktionen und angegebene Funktionsargumente sowie ihre entsprechenden Typen und Einschränkungen zu dekorieren.
Hier definieren wir Modelle, indem wir Modellklassen definieren, in denen wir Felder, ihre Typen und Einschränkungen angeben. Dies ist sehr ähnlich zu dem, was wir zuvor getan haben. Indem wir eine Modellklasse definieren, die von Pydantic erbt BaseModel
verwenden wir einen versteckten Mechanismus, der die Datenvalidierung, -analyse und -serialisierung durchführt. Dadurch können wir Objekte erstellen, die den Modellspezifikationen entsprechen.
Hier ist ein Beispiel:
from pydantic import Subject
from pydantic import BaseModelclass Individual(BaseModel):
identify: str = Subject(min_length=2, max_length=15)
age: int = Subject(gt=0, lt=120)
# ----
john = Individual(identify='john', age=20)
> Individual(identify='john', age=20)
# ----
mike = Individual(identify='m', age=0)
> ValidationError: 2 validation errors for Individual
identify
String ought to have at the very least 2 characters (kind=string_too_short, input_value='j', input_type=str)
For additional data go to <https://errors.pydantic.dev/2.5/v/string_too_short>
age
Enter ought to be larger than 0 (kind=greater_than, input_value=0, input_type=int)
For additional data go to <https://errors.pydantic.dev/2.5/v/greater_than>
Sie können hier auch Anmerkungen verwenden und Standardwerte für Felder angeben. Sehen wir uns ein weiteres Beispiel an:
from pydantic import Subject
from pydantic import BaseModel
from typing import Annotated Identify = Annotated(str, Subject(min_length=2, max_length=15))
Age = Annotated(int, Subject(default=1, ge=0, le=120))
class Individual(BaseModel):
identify: Identify
age: Age
# ----
mike = Individual(identify='mike')
> Individual(identify='mike', age=1)
Die Dinge werden sehr interessant, wenn Ihr Anwendungsfall etwas komplexer wird. Denken Sie daran, payload
die wir definiert haben? Ich werde eine andere, komplexere Struktur definieren, die wir durchgehen und validieren werden. Um es interessanter zu machen, erstellen wir eine Nutzlast, die wir verwenden, um einen Dienst abzufragen, der als Vermittler zwischen uns und LLM-Anbietern fungiert. Dann werden wir es validieren.
Hier ist ein Beispiel:
from pydantic import Subject
from pydantic import BaseModel
from pydantic import ConfigDictfrom typing import Literal
from typing import Annotated
from enum import Enum
payload = {
"req_id": "take a look at",
"textual content": "It is a pattern textual content.",
"instruction": "embed",
"llm_provider": "openai",
"llm_params": {
"llm_temperature": 0,
"llm_model_name": "gpt4o"
},
"misc": "what"
}
ReqID = Annotated(str, Subject(min_length=2, max_length=15))
class LLMProviders(str, Enum):
OPENAI = 'openai'
CLAUDE = 'claude'
class LLMParams(BaseModel):
temperature: int = Subject(validation_alias='llm_temperature', ge=0, le=1)
llm_name: str = Subject(validation_alias='llm_model_name',
serialization_alias='mannequin')
class Payload(BaseModel):
req_id: str = Subject(exclude=True)
textual content: str = Subject(min_length=5)
instruction: Literal('embed', 'chat')
llm_provider: LLMProviders
llm_params: LLMParams
# model_config = ConfigDict(use_enum_values=True)
# ----
validated_payload = Payload(**payload)
validated_payload
> Payload(req_id='take a look at',
textual content='It is a pattern textual content.',
instruction='embed',
llm_provider=<LLMProviders.OPENAI: 'openai'>,
llm_params=LLMParams(temperature=0, llm_name='gpt4o'))
# ----
validated_payload.model_dump()
> {'textual content': 'It is a pattern textual content.',
'instruction': 'embed',
'llm_provider': <LLMProviders.OPENAI: 'openai'>,
'llm_params': {'temperature': 0, 'llm_name': 'gpt4o'}}
# ----
validated_payload.model_dump(by_alias=True)
> {'textual content': 'It is a pattern textual content.',
'instruction': 'embed',
'llm_provider': <LLMProviders.OPENAI: 'openai'>,
'llm_params': {'temperature': 0, 'mannequin': 'gpt4o'}}
# ----
# After including
# model_config = ConfigDict(use_enum_values=True)
# in Payload mannequin definition, you get
validated_payload.model_dump(by_alias=True)
> {'textual content': 'It is a pattern textual content.',
'instruction': 'embed',
'llm_provider': 'openai',
'llm_params': {'temperature': 0, 'mannequin': 'gpt4o'}}
Einige der wichtigen Erkenntnisse aus diesem ausführlichen Beispiel sind:
- Sie können Enums verwenden oder
Literal
um eine Liste spezifischer Werte zu definieren, die erwartet werden. - Wenn Sie ein Modellfeld anders benennen möchten als in den validierten Daten, können Sie
validation_alias
. Es gibt den Feldnamen in den zu validierenden Daten an. serialization_alias
wird verwendet, wenn der interne Feldname des Modells nicht unbedingt derselbe Identify ist, den Sie beim Serialisieren des Modells verwenden möchten.- Felder können von der Serialisierung ausgeschlossen werden mit
exclude=True
. - Modellfelder können auch Pydantic-Modelle sein. Der Validierungsprozess wird in diesem Fall rekursiv durchgeführt. Dieser Teil ist wirklich großartig, da Pydantic bei der Validierung verschachtelter Strukturen in die Tiefe geht.
- Felder, die in der Modelldefinition nicht berücksichtigt werden, werden nicht geparst.
Hier zeige ich Ihnen Codeausschnitte, die verdeutlichen, wo und wie Sie Pydantic in Ihren täglichen Aufgaben verwenden können.
Angenommen, Sie haben Daten, die Sie validieren und verarbeiten müssen. Sie können in CSV- oder Parquet-Dateien oder beispielsweise in einer NoSQL-Datenbank in Kind eines Dokuments gespeichert sein. Nehmen wir das Beispiel einer CSV-Datei und nehmen wir an, Sie möchten deren Inhalt verarbeiten.
Hier ist die CSV-Datei (take a look at.csv
) Beispiel:
identify,age,bank_account
johnny,0,20
matt,10,0
abraham,100,100000
mary,15,15
linda,130,100000
Und so wird es validiert und analysiert:
from pydantic import BaseModel
from pydantic import Subject
from pydantic import field_validator
from pydantic import ValidationInfo
from typing import Listing
import csvFILE_NAME = 'take a look at.csv'
class DataModel(BaseModel):
identify: str = Subject(min_length=2, max_length=15)
age: int = Subject(ge=1, le=120)
bank_account: float = Subject(ge=0, default=0)
@field_validator('identify')
@classmethod
def validate_name(cls, v: str, information: ValidationInfo) -> str:
return str(v).capitalize()
class ValidatedModels(BaseModel):
validated: Listing(DataModel)
validated_rows = ()
with open(FILE_NAME, 'r') as f:
reader = csv.DictReader(f, delimiter=',')
for row in reader:
attempt:
validated_rows.append(DataModel(**row))
besides ValidationError as ve:
# print out error
# disregard the report
print(f'{ve=}')
validated_rows
> (DataModel(identify='Matt', age=10, bank_account=0.0),
DataModel(identify='Abraham', age=100, bank_account=100000.0),
DataModel(identify='Mary', age=15, bank_account=15.0))
validated = ValidatedModels(validated=validated_rows)
validated.model_dump()
> {'validated': ({'identify': 'Matt', 'age': 10, 'bank_account': 0.0},
{'identify': 'Abraham', 'age': 100, 'bank_account': 100000.0},
{'identify': 'Mary', 'age': 15, 'bank_account': 15.0})}
FastAPI ist bereits in Pydantic integriert, daher wird dieser Artikel sehr kurz gehalten. FastAPI verarbeitet Anfragen, indem es sie an eine Funktion weiterleitet, die die Route verarbeitet. Durch die Weiterleitung dieser Anfrage an eine Funktion wird die Validierung automatisch durchgeführt. Etwas Ähnliches wie validate_call, das wir am Anfang dieses Artikels erwähnt haben.
Beispiel von app.py
das zum Ausführen eines auf FastAPI basierenden Dienstes verwendet wird:
from fastapi import FastAPI
from pydantic import BaseModel, HttpUrlclass Request(BaseModel):
request_id: str
url: HttpUrl
app = FastAPI()
@app.submit("/search/by_url/")
async def create_item(req: Request):
return merchandise
Pydantic ist eine wirklich leistungsstarke Bibliothek und verfügt über zahlreiche Mechanismen für eine Vielzahl unterschiedlicher Anwendungsfälle und Randfälle. Heute habe ich die grundlegendsten Aspekte der Verwendung erklärt und werde unten Referenzen für diejenigen bereitstellen, die nicht schwache Nerven haben.
Gehen Sie auf Entdeckungsreise. Ich bin sicher, es wird Ihnen in vielerlei Hinsicht von Nutzen sein.