Examples
The best way to understand cheap-settings is through examples. All examples are runnable - you can copy and paste them into Python files.
Basic Usage
The simplest way to use cheap-settings:
from cheap_settings import CheapSettings
class AppSettings(CheapSettings):
"""Application configuration."""
host: str = "localhost"
port: int = 8080
debug: bool = False
app_name: str = "MyApp"
# Access settings directly as class attributes
print(f"Host: {AppSettings.host}")
print(f"Port: {AppSettings.port}")
print(f"Server: http://{AppSettings.host}:{AppSettings.port}")
Environment Variables
Environment variables automatically override defaults with type conversion:
import os
from cheap_settings import CheapSettings
class Settings(CheapSettings):
database_host: str = "localhost"
database_port: int = 5432
connection_timeout: float = 30.0
use_ssl: bool = False
# Set environment variables
os.environ["DATABASE_HOST"] = "prod.example.com"
os.environ["DATABASE_PORT"] = "3306" # Converted to int
os.environ["USE_SSL"] = "true" # Converted to bool
print(f"Database: {Settings.database_host}:{Settings.database_port}")
print(f"SSL: {Settings.use_ssl} ({type(Settings.use_ssl).__name__})")
Command Line Arguments
Automatically create CLI arguments from your settings:
from cheap_settings import CheapSettings
class ServerConfig(CheapSettings):
host: str = "0.0.0.0"
port: int = 8000
workers: int = 4
reload: bool = False
# Parse command line arguments
ServerConfig.set_config_from_command_line()
print(f"Server: {ServerConfig.host}:{ServerConfig.port}")
print(f"Workers: {ServerConfig.workers}")
Run with: python server.py --host localhost --port 3000 --workers 8 --reload
Inheritance
Settings classes can inherit from each other:
from cheap_settings import CheapSettings
class BaseConfig(CheapSettings):
app_name: str = "MyApplication"
version: str = "1.0.0"
timeout: int = 30
class DatabaseConfig(BaseConfig):
db_host: str = "localhost"
db_port: int = 5432
db_name: str = "myapp"
class ProductionConfig(DatabaseConfig):
debug: bool = False
db_host: str = "prod.db.example.com" # Override parent
ssl_required: bool = True
print(f"App: {ProductionConfig.app_name} v{ProductionConfig.version}")
print(f"Database: {ProductionConfig.db_host}:{ProductionConfig.db_port}")
Type Conversion
All basic Python types are supported, with or without type annotations:
from pathlib import Path
from typing import Optional
from cheap_settings import CheapSettings
class TypedSettings(CheapSettings):
# Explicit type annotations
text: str = "default"
number: int = 42
ratio: float = 3.14
enabled: bool = False
# Type inference from defaults (no annotations needed!)
host = "localhost" # Infers str
port = 8080 # Infers int
timeout = 30.5 # Infers float
debug = False # Infers bool
# Path support
config_dir: Path = Path("/etc/myapp")
# Or inferred:
log_dir = Path("/var/log") # Infers Path
# JSON types
tags: list = ["python", "config"]
metadata: dict = {"version": 1}
# Optional types (need explicit annotation)
api_key: Optional[str] = None
# Environment variables are converted automatically:
# TEXT="hello" NUMBER="99" ENABLED="true" CONFIG_DIR="/custom/path"
# TAGS='["web", "api"]' METADATA='{"env": "prod"}' API_KEY="secret"
Static Snapshots
For performance-critical code, create static snapshots:
from cheap_settings import CheapSettings
class DynamicSettings(CheapSettings):
api_url: str = "https://api.example.com"
timeout: int = 30
retry_count: int = 3
# Create a static snapshot (frozen values)
StaticSettings = DynamicSettings.to_static()
# Static class has no dynamic behavior - just fast attribute access
print(f"API: {StaticSettings.api_url}")
print(f"Type: {type(StaticSettings)}") # Regular Python class
Pickle Support
Works with Ray and other frameworks requiring serialization:
import pickle
from cheap_settings import CheapSettings
class Config(CheapSettings):
host: str = "localhost"
port: int = 8080
# Pickle and unpickle
pickled = pickle.dumps(Config)
unpickled_class = pickle.loads(pickled)
assert unpickled_class.host == Config.host
print("✓ Pickle support works!")
More Examples
For complete runnable examples, see the examples directory in the repository.