这是一个完整的脚本,包含一个继承 Pydantic 的 BaseModel 的新类 BaseModelNoException,包装了异常 ValidationError 并改为抛出警告。
import json
from traceback import TracebackException
from typing import no_type_check, Type, Any
from pydantic import BaseModel, NonNegativeInt, ValidationError, StrBytes, Protocol
class BaseModelNoException(BaseModel):
def __init__(__pydantic_self__, **data: Any) -> None:
try:
super(BaseModelNoException, __pydantic_self__).__init__(**data)
except ValidationError as pve:
print(f'This is a warning. __init__ failed to validate:\n {json.dumps(data, indent=4)}\n')
print(f'This is the original exception:\n{pve.json()}')
@no_type_check
def __setattr__(self, name, value):
try:
return super(BaseModelNoException, self).__setattr__
except ValidationError as pve:
print(f'This is a warning. __setattr__ failed to validate:\n {json.dumps({name: value}, indent=4)}')
print(f'This is the original exception:\n{pve.json()}')
return None
@classmethod
def parse_obj(cls: Type['Model'], obj: Any) -> 'Model':
try:
return super(BaseModelNoException, cls).parse_obj(obj)
except ValidationError as pve:
print(f'This is a warning. parse_obj failed to validate:\n {json.dumps(obj, indent=4)}')
print(f'This is the original exception:\n{pve.json()}')
return None
@classmethod
def parse_raw(cls: Type['Model'], b: StrBytes, *, content_type: str = None, encoding: str = 'utf8',
proto: Protocol = None, allow_pickle: bool = False, ) -> 'Model':
try:
return super(BaseModelNoException, cls).parse_raw(b=b, content_type=content_type, encoding=encoding,
proto=proto, allow_pickle=allow_pickle)
except ValidationError as pve:
print(f'This is a warning. parse_raw failed to validate:\n {b}')
print(f'This is the original exception:\n{pve.json()}')
return None
# class Person(BaseModel):
class PersonDetails(BaseModel):
height: NonNegativeInt
weight: NonNegativeInt
class Person(BaseModelNoException):
name: str = ''
age: NonNegativeInt = 0
details: PersonDetails
p1: Person = Person(name='Alice', age=30, details=None)
print(p1)
print('-' * 100)
p2: Person = Person(name='Bob', age=40, details={'height': 1.70, 'weight': 91})
print(p2)
print('-' * 100)
p3: Person = Person.parse_obj({'name': 'Alice', 'age': 31, 'details': {'height': 1.70, 'weight': -77}})
print(p3)
print('-' * 100)
print('The End')
这是上面脚本的输出。
/playground/test_pydantic_prevent_exception.py
这是一个警告。 init 验证失败:
{
“名称”:“爱丽丝”,
“年龄”:30,
“详细信息”:空
}
This is the original exception:
[
{
"loc": [
"details"
],
"msg": "none is not an allowed value",
"type": "type_error.none.not_allowed"
}
]
----------------------------------------------------------------------------------------------------
name='Bob' age=40 details=PersonDetails(height=1, weight=91)
----------------------------------------------------------------------------------------------------
This is a warning. __init__ failed to validate:
{
"name": "Alice",
"age": 31,
"details": {
"height": 1.7,
"weight": -77
}
}
This is the original exception:
[
{
"loc": [
"details",
"weight"
],
"msg": "ensure this value is greater than or equal to 0",
"type": "value_error.number.not_ge",
"ctx": {
"limit_value": 0
}
}
]
----------------------------------------------------------------------------------------------------
The End
Process finished with exit code 0