Pydantic:保存嵌套设置
Pydantic: Save nested settings
我目前正在尝试在更改时自动将 pydantic.BaseSettings
对象保存到 json 文件。该模型是预先从 json-File 中加载的。保存过程的最小工作示例如下:
import json
from pydantic import BaseModel, BaseSettings, root_validator
from typing import Any, Dict
class NestedSettings(BaseModel):
test: str = 'foobar'
class Settings(BaseSettings):
nested: NestedSettings = NestedSettings()
foo: str = 'bar'
@root_validator
def save_settings(cls, values: Dict[str, Any]) -> Dict[str, Any]:
print('SAVING!')
def serialize_basemodel(model: BaseModel):
if isinstance(model, BaseModel):
return model.dict()
else:
raise TypeError(f'{type(model)} is not serializable!')
with open('config.json', 'w', encoding='utf-8') as f:
json.dump(values, f, ensure_ascii=False, indent=2,
default=serialize_basemodel)
return values
class Config:
validate_assignment: bool = True
s = Settings()
print('Saving top level:')
s.foo = 'baz'
print('Saving bottom level:')
s.nested.test = 'bar'
生成的输出是:
SAVING!
Saving top level:
SAVING!
Saving bottom level:
即使分配了底层 s.nested.bar
,我也想让对象保存。有什么办法可以实现吗?
提前感谢任何提示!
我的回答不够优雅,但由于 validate_assignment 似乎只检查根字段,您仍然可以通过更改
来利用该操作
s.nested.test
到
s.nested = {'test': 'bar'}
它会起作用的。这是示例代码和输出,以便更好地演示。
class Settings(BaseSettings):
nested: NestedSettings = NestedSettings()
foo: str = 'bar'
@root_validator(pre=False)
def save_settings(cls, values: Dict[str, Any]) -> Dict[str, Any]:
print('SAVING!')
print(values)
def serialize_basemodel(model: BaseModel):
if isinstance(model, BaseModel):
return model.dict()
else:
raise TypeError(f'{type(model)} is not serializable!')
with open('config.json', 'w', encoding='utf-8') as f:
json.dump(values, f, ensure_ascii=False, indent=2,
default=serialize_basemodel)
return values
class Config:
validate_assignment: bool = True
s = Settings()
print('Saving top level:')
s.foo = 'baz'
print('Saving bottom level:')
s.nested = {'test': 'bar'}
SAVING!
{'nested': NestedSettings(test='foobar'), 'foo': 'bar'}
Saving top level:
SAVING!
{'nested': NestedSettings(test='foobar'), 'foo': 'baz'}
Saving bottom level:
SAVING!
{'nested': NestedSettings(test='bar'), 'foo': 'baz'}
我目前正在尝试在更改时自动将 pydantic.BaseSettings
对象保存到 json 文件。该模型是预先从 json-File 中加载的。保存过程的最小工作示例如下:
import json
from pydantic import BaseModel, BaseSettings, root_validator
from typing import Any, Dict
class NestedSettings(BaseModel):
test: str = 'foobar'
class Settings(BaseSettings):
nested: NestedSettings = NestedSettings()
foo: str = 'bar'
@root_validator
def save_settings(cls, values: Dict[str, Any]) -> Dict[str, Any]:
print('SAVING!')
def serialize_basemodel(model: BaseModel):
if isinstance(model, BaseModel):
return model.dict()
else:
raise TypeError(f'{type(model)} is not serializable!')
with open('config.json', 'w', encoding='utf-8') as f:
json.dump(values, f, ensure_ascii=False, indent=2,
default=serialize_basemodel)
return values
class Config:
validate_assignment: bool = True
s = Settings()
print('Saving top level:')
s.foo = 'baz'
print('Saving bottom level:')
s.nested.test = 'bar'
生成的输出是:
SAVING!
Saving top level:
SAVING!
Saving bottom level:
即使分配了底层 s.nested.bar
,我也想让对象保存。有什么办法可以实现吗?
提前感谢任何提示!
我的回答不够优雅,但由于 validate_assignment 似乎只检查根字段,您仍然可以通过更改
来利用该操作s.nested.test
到
s.nested = {'test': 'bar'}
它会起作用的。这是示例代码和输出,以便更好地演示。
class Settings(BaseSettings):
nested: NestedSettings = NestedSettings()
foo: str = 'bar'
@root_validator(pre=False)
def save_settings(cls, values: Dict[str, Any]) -> Dict[str, Any]:
print('SAVING!')
print(values)
def serialize_basemodel(model: BaseModel):
if isinstance(model, BaseModel):
return model.dict()
else:
raise TypeError(f'{type(model)} is not serializable!')
with open('config.json', 'w', encoding='utf-8') as f:
json.dump(values, f, ensure_ascii=False, indent=2,
default=serialize_basemodel)
return values
class Config:
validate_assignment: bool = True
s = Settings()
print('Saving top level:')
s.foo = 'baz'
print('Saving bottom level:')
s.nested = {'test': 'bar'}
SAVING!
{'nested': NestedSettings(test='foobar'), 'foo': 'bar'}
Saving top level:
SAVING!
{'nested': NestedSettings(test='foobar'), 'foo': 'baz'}
Saving bottom level:
SAVING!
{'nested': NestedSettings(test='bar'), 'foo': 'baz'}