Загрузка настроек из env-переменных, .env-файлов, CLI-аргументов. Приоритеты источников.
Pydantic Settings загружает конфигурацию из env-переменных, .env-файлов и других источников
pip install pydantic-settingsfrom pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
app_name: str = "MyApp"
debug: bool = False
database_url: str
model_config = SettingsConfigDict(
env_file='.env',
env_file_encoding='utf-8'
)
settings = Settings()
print(settings.app_name) # "MyApp" или из env
print(settings.database_url) # из env или .envfrom pydantic_settings import BaseSettings
class Settings(BaseSettings):
app_name: str = "DefaultApp" # 4. По умолчанию
debug: bool = False
# .env:
# APP_NAME=FromEnv
# DEBUG=true
# Запуск:
# 1. Переменные окружения: export APP_NAME=FromEnv
# 2. settings = Settings() # APP_NAME из env
# 3. settings = Settings(app_name="FromInit") # из аргументаfrom pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
database_url: str
redis_host: str = "localhost"
redis_port: int = 6379
model_config = SettingsConfigDict(
env_file='.env', # путь к файлу
env_file_encoding='utf-8'
)
# .env файл:
# DATABASE_URL=postgres://user:pass@localhost/db
# REDIS_HOST=127.0.0.1
# REDIS_PORT=6380
settings = Settings()from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
database_url: str
database_pool_size: int = 10
model_config = SettingsConfigDict(
env_prefix='MYAPP_' # префикс
)
# Переменные окружения:
# MYAPP_DATABASE_URL=postgres://...
# MYAPP_DATABASE_POOL_SIZE=20
settings = Settings()from pydantic_settings import BaseSettings, Field
class Settings(BaseSettings):
database_url: str = Field(alias='DB_URL')
redis_host: str = "localhost"
model_config = SettingsConfigDict(
populate_by_name=True # принимать оба имени
)
# Работают оба варианта:
# export DB_URL=postgres://...
# export DATABASE_URL=postgres://...
settings = Settings()from pydantic_settings import BaseSettings
from pydantic import Field
class DatabaseSettings(BaseSettings):
url: str
pool_size: int = 10
echo: bool = False
class Settings(BaseSettings):
database: DatabaseSettings
model_config = SettingsConfigDict(
env_nested_delimiter='__' # разделитель для вложенности
)
# Переменные окружения:
# DATABASE__URL=postgres://...
# DATABASE__POOL_SIZE=20
# DATABASE__ECHO=true
settings = Settings()
print(settings.database.url) # "postgres://..."
print(settings.database.pool_size) # 20Pydantic Settings автоматически преобразует типы:
from pydantic_settings import BaseSettings
from typing import List, Dict
from datetime import timedelta
class Settings(BaseSettings):
# Числа
port: int = 8000
timeout: float = 30.5
# Булевы (true, false, 1, 0, yes, no, on, off)
debug: bool = False
# Списки (через запятую)
allowed_hosts: list[str] = ["localhost"]
# export ALLOWED_HOSTS=host1,host2,host3
# Словари (JSON)
metadata: dict[str, str] = {}
# export METADATA='{"key": "value"}'
# timedelta
session_timeout: timedelta = timedelta(hours=1)
# export SESSION_TIMEOUT=3600 (секунды)
settings = Settings()from pydantic_settings import BaseSettings, SettingsConfigDict
from pydantic import SecretStr
class Settings(BaseSettings):
database_password: SecretStr
api_key: SecretStr
model_config = SettingsConfigDict(
env_file='.env'
)
settings = Settings()
# Получение значения
print(settings.database_password.get_secret_value())
# При выводе значение скрыто
print(settings) # database_password=SecretStr('**********')from pydantic_settings import BaseSettings, SettingsConfigDict
from pydantic import Field, field_validator
class Settings(BaseSettings):
database_url: str
debug: bool = False
log_level: str = "info"
model_config = SettingsConfigDict(env_file='.env')
@field_validator('database_url')
@classmethod
def validate_database_url(cls, v: str) -> str:
if not v.startswith(('postgres://', 'mysql://', 'sqlite://')):
raise ValueError('Invalid database URL scheme')
return v
@field_validator('log_level')
@classmethod
def validate_log_level(cls, v: str) -> str:
allowed = ['debug', 'info', 'warning', 'error', 'critical']
if v.lower() not in allowed:
raise ValueError(f'Log level must be one of {allowed}')
return v.lower()
try:
settings = Settings()
except Exception as e:
print(f"Configuration error: {e}")from pydantic_settings import BaseSettings, SettingsConfigDict
from pathlib import Path
class Settings(BaseSettings):
app_name: str = "MyApp"
debug: bool = False
model_config = SettingsConfigDict(
env_file=[
'.env.base', # базовые настройки
'.env.local', # локальные переопределения
'.env.secret' # секреты (в .gitignore)
],
env_file_encoding='utf-8'
)
settings = Settings()import os
from pydantic_settings import BaseSettings, SettingsConfigDict
env = os.getenv('APP_ENV', 'development')
class Settings(BaseSettings):
app_name: str = "MyApp"
model_config = SettingsConfigDict(
env_file=f'.env.{env}'
)
settings = Settings()from pydantic_settings import BaseSettings, SettingsConfigDict
from pydantic import HttpUrl, SecretStr
class Settings(BaseSettings):
# App
app_name: str = "My API"
debug: bool = False
environment: str = "development"
# Server
host: str = "0.0.0.0"
port: int = 8000
# Database
database_url: SecretStr
# Redis
redis_url: str = "redis://localhost:6379"
# CORS
cors_origins: list[str] = ["*"]
model_config = SettingsConfigDict(
env_file='.env',
env_prefix='API_'
)
settings = Settings()from pydantic_settings import BaseSettings, SettingsConfigDict
class DevSettings(BaseSettings):
debug: bool = True
database_url: str = "sqlite:///dev.db"
model_config = SettingsConfigDict(
env_file='.env.dev',
env_prefix='DEV_'
)
class ProdSettings(BaseSettings):
debug: bool = False
database_url: str
model_config = SettingsConfigDict(
env_file='.env.prod',
env_prefix='PROD_'
)
# Выбор настроек
import os
env = os.getenv('APP_ENV', 'dev')
if env == 'production':
settings = ProdSettings()
else:
settings = DevSettings()Создайте полную конфигурацию для микросервиса:
from pydantic_settings import BaseSettings, SettingsConfigDict
from pydantic import Field, SecretStr, HttpUrl, field_validator
from typing import List, Optional
from datetime import timedelta
class DatabaseConfig(BaseSettings):
# url: SecretStr
# pool_size: int = 10
# echo: bool = False
pass
class RedisConfig(BaseSettings):
# url: str = "redis://localhost:6379"
# db: int = 0
# password: Optional[SecretStr] = None
pass
class JWTConfig(BaseSettings):
# secret_key: SecretStr
# algorithm: str = "HS256"
# access_token_expire_minutes: int = 30
pass
class ServiceSettings(BaseSettings):
# name: str
# version: str = "1.0.0"
# environment: str = "development"
# debug: bool = False
# database: DatabaseConfig
# redis: RedisConfig
# jwt: JWTConfig
# allowed_origins: list[str] = ["*"]
# request_timeout: timedelta = timedelta(seconds=30)
# Добавьте валидаторы:
# - environment должен быть one of: development, staging, production
# - version должен соответствовать semver (опционально)
model_config = SettingsConfigDict(
env_file='.env',
env_prefix='SERVICE_',
env_nested_delimiter='__'
)
# .env файл:
# SERVICE_NAME=my-service
# SERVICE_VERSION=1.0.0
# SERVICE_ENVIRONMENT=development
# SERVICE_DEBUG=true
# SERVICE_DATABASE__URL=postgres://user:pass@localhost/db
# SERVICE_DATABASE__POOL_SIZE=20
# SERVICE_REDIS__URL=redis://localhost:6379
# SERVICE_JWT__SECRET_KEY=supersecret
# SERVICE_JWT__ALGORITHM=HS256В следующей теме изучим интеграцию с FastAPI для валидации запросов и ответов.
Вопросы ещё не добавлены
Вопросы для этой подтемы ещё не добавлены.