pydantic

J. Hwang·2024년 12월 17일

pydantic은 데이터 검증 및 설정 관리를 위해 사용하는 python 라이브러리이다. 데이터 모델링을 위한 python 클래스와 타입 힌트를 기반으로 작동하며, 주로 FastAPI와 같은 프레임워크에서 많이 사용된다.


핵심 기능

  • 데이터 검증 (Validation) : 입력된 데이터가 선언된 타입 힌트와 일치하는지 확인하고, 일치하지 않으면 에러 반환
  • 데이터 직렬화 및 역직렬화 : 데이터를 JSON 형태로 쉽게 직렬화하거나, JSON 데이터를 Python 객체로 역직렬화
  • 사용자 친화적 에러 메시지 : 데이터 검증에서 실패한 이유를 명확히 알려주는 에러 메시지를 제공

validation

input 데이터가 1) 올바른 url, 2) 1-10 사이의 정수, 3) 올바른 폴더 이름을 입력했는지 검증해보자.

from pydantic import BaseModel, HttpUrl, Field, DirectoryPath

class Validation(BaseModel):
    url: HttpUrl        # 올바른 url인가?
    rate: int = Field(ge=1, le=10)     # 1-10 사이의 정수인가?
    target_dir: DirectoryPath     # 존재하는 디렉토리인가?

일반 python class나 dataclass 라이브러리를 사용할 수도 있지만, pydantic을 활용하면 훨씬 간결하게 validation을 할 수 있다. 자주 쓰이는 타입들(http url, db url, enum, ...)에 대한 validation은 이미 만들어져 있다. custom type에 대한 validation은 여기 참조.

from pydantic import ValidationError

VALID_INPUT = {
        "url": "https://content.presspage.com/uploads/2658/c800_logo-stackoverflow-square.jpg?98978",
        "rate": 4,
        "target_dir": os.path.join(os.getcwd(), "examples"),
    }

INVALID_INPUT = {"url": "WRONG_URL", "rate": 11, "target_dir": "WRONG_DIR"}

valid_pydantic_model_input = Validation(**VALID_INPUT)

try:
	invalid_pydantic_model_input = Validation(**INVALID_INPUT)   # error
except ValidationError as exc:
	print("pydantic model input validation error: ", exc.json())

작성한 Validation 클래스를 이용해서 위와 같이 제대로 된 데이터를 입력했는지 검증할 수 있다. 어디서 에러가 발생했는지, location, type, message 등을 알려준다.


Config

configuration은 코드 내에 상수로 작성하거나, yaml 파일로 관리할 수도 있지만, 배포 환경 별로 yaml 파일을 생성해야하는 번거로움도 있고, 보안 정보가 파일에 노출되기 때문에 주의가 필요하다.

from pydantic import BaseSettings, Field
from enum import Enum

class ConfigEnv(str, Enum):
    DEV = "dev"
    PROD = "prod"

class DBConfig(BaseSettings):
    host: str = Field(default="localhost", env="db_host")
    port: int = Field(default=3306, env="db_port")
    username: str = Field(default="user", env="db_username")
    password: str = Field(default="user", env="db_password")
    database: str = Field(default="dev", env="db_database")

class AppConfig(BaseSettings):
    env: ConfigEnv = Field(default="dev", env="env")
    db: DBConfig = DBConfig()

with open("dev_config.yaml", "r") as f:
    config = load(f, FullLoader)

config_with_pydantic = AppConfig(**config)

assert config_with_pydantic.env == "dev"
assert config_with_pydantic.db.dict() == expected

그러나 pydantic을 이용하면 환경 변수에 설정 값을 저장하고 코드에서 환경 변수를 읽어오기 때문에 보안 정보가 노출되지 않는다. yaml 등의 파일을 추가적으로 만들지 않아도 된다.

# 환경 변수로 필드를 오버라이딩
os.environ["ENV"] = "prod"
os.environ["DB_HOST"] = "mysql"
os.environ["DB_USERNAME"] = "admin"
os.environ["DB_PASSWORD"] = "PASSWORD"

prod_config_with_pydantic = AppConfig()
assert prod_config_with_pydantic.env == "prod"
assert prod_config_with_pydantic.dict() != expected

# cleanup
os.remove("dev_config.yaml")

References

https://github.com/zzsza/Boostcamp-AI-Tech-Product-Serving/tree/main/02-online-serving(fastapi)/examples

profile
Let it code

0개의 댓글