의존 패키지를 올렸더니 기존 설정 클래스가 뜨지 않는다.
PydanticImportError: `BaseSettings` has been moved to the `pydantic-settings` package.
Pydantic 2.0 에서 BaseSettings 는 본체에서 빠져 pydantic-settings 라는 별도 패키지로 나갔다. 환경변수 읽기는 데이터 검증과 다른 관심사라는 판단이었다. 이름만 옮긴 것이 아니라 설정 방식도 함께 바뀌었다.
설치부터 한다.
pip install pydantic-settings
가져오는 자리를 바꾼다.
# v1
from pydantic import BaseSettings
# v2
from pydantic_settings import BaseSettings, SettingsConfigDict
내부 설정 클래스 class Config 는 model_config 로 바뀌었다.
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
env_prefix="APP_",
extra="ignore",
)
db_host: str
db_port: int = 1521
debug: bool = False
settings = Settings()
extra="ignore" 를 빼면 v2 는 정의되지 않은 환경변수를 만났을 때 오류를 낸다. v1 은 무시했으므로 이전 중에 가장 자주 걸리는 지점이다.
| v1 | v2 |
|---|---|
class Config: |
model_config = ConfigDict(...) |
@validator |
@field_validator |
@root_validator |
@model_validator |
.dict() |
.model_dump() |
.json() |
.model_dump_json() |
parse_obj() |
model_validate() |
Field(..., env="X") |
Field(..., validation_alias="X") |
allow_mutation = False |
model_config = ConfigDict(frozen=True) |
Optional[str] 에 기본값을 주지 않으면 v2 는 필수 항목으로 본다. v1 은 None 을 기본값으로 쳤다. 이 차이로 기동 시 검증 오류가 무더기로 나는 경우가 있다.
# v2 에서는 이렇게 써야 v1 과 같은 뜻이 된다
name: str | None = None
공식 변환 도구가 기계적인 부분을 바꿔 준다. 결과는 반드시 검토한다.
pip install bump-pydantic
bump-pydantic ./src
다른 의존 패키지가 v1 을 요구해 함께 올리기 어려우면, v2 안에 들어 있는 v1 호환 이름공간을 임시로 쓸 수 있다.
from pydantic.v1 import BaseModel, validator
다만 이것은 이행 기간용이다. 한 프로세스 안에서 v1 모델과 v2 모델을 섞으면 서로의 타입을 인식하지 못해 중첩 모델에서 문제가 생긴다.
pydantic-settings 의 버전도 본체와 맞아야 한다. 요구사항 파일에 두 패키지를 함께 고정한다.
FastAPI 는 0.100 부터 Pydantic v2 를 지원한다. 그 이전 버전과 v2 를 섞으면 응답 모델 직렬화에서 깨진다.
검증 오류 메시지 형식이 바뀌었으므로, 오류 본문을 파싱하던 코드가 있으면 함께 고쳐야 한다.