A framework for elegantly configuring complex applications
—
Context managers for programmatic Hydra initialization in different scenarios. These enable using Hydra's configuration composition capabilities outside of the main application decorator pattern.
Initializes Hydra with configuration files from a directory path relative to the calling module.
class initialize:
def __init__(
self,
config_path: Optional[str] = None,
job_name: Optional[str] = None,
caller_stack_depth: int = 1,
version_base: Optional[str] = None
) -> None:
"""
Initialize Hydra with config path relative to caller.
Parameters:
- config_path: Path relative to the parent of the caller.
Can use "pkg://" prefix for package resources.
If None, no directory is added to config search path.
- job_name: Value for hydra.job.name (auto-detected if None)
- caller_stack_depth: Stack depth of caller (default 1 for direct caller)
- version_base: Hydra version compatibility base
"""Initializes Hydra with configurations from an importable Python module.
class initialize_config_module:
def __init__(
self,
config_module: str,
job_name: str = "app",
version_base: Optional[str] = None
) -> None:
"""
Initialize Hydra with config module.
Parameters:
- config_module: Absolute module name (e.g., "foo.bar.conf")
Module must be importable with __init__.py
- job_name: Value for hydra.job.name (default "app")
- version_base: Hydra version compatibility base
"""Initializes Hydra with configurations from an absolute directory path.
class initialize_config_dir:
def __init__(
self,
config_dir: str,
job_name: str = "app",
version_base: Optional[str] = None
) -> None:
"""
Initialize Hydra with absolute config directory.
Parameters:
- config_dir: Absolute filesystem path to config directory
- job_name: Value for hydra.job.name (default "app")
- version_base: Hydra version compatibility base
Raises:
HydraException: If config_dir is not an absolute path
"""from hydra import initialize, compose
# Initialize with relative path
with initialize(version_base=None, config_path="conf"):
cfg = compose(config_name="config")
print(cfg.db.driver)
# Initialize with package path
with initialize(version_base=None, config_path="pkg://my_package.conf"):
cfg = compose(config_name="config")
print(cfg)
# Initialize with no config path (structured configs only)
with initialize(version_base=None, config_path=None):
cfg = compose(config_name="config") # Must exist in ConfigStorefrom hydra import initialize_config_module, compose
# Initialize with Python module
with initialize_config_module(version_base=None, config_module="my_app.conf"):
cfg = compose(config_name="config")
# Custom job name
with initialize_config_module(
version_base=None,
config_module="my_app.conf",
job_name="custom_job"
):
cfg = compose(config_name="config")
print(cfg.hydra.job.name) # Will be "custom_job"from hydra import initialize_config_dir, compose
import os
# Must use absolute path
config_dir = os.path.abspath("./conf")
with initialize_config_dir(version_base=None, config_dir=config_dir):
cfg = compose(config_name="config")
# Error: relative path not allowed
try:
with initialize_config_dir(version_base=None, config_dir="./conf"):
pass
except HydraException as e:
print("Relative paths not allowed")Initialization contexts can be nested and properly restore state:
from hydra import initialize, compose
# Outer context
with initialize(version_base=None, config_path="conf1"):
cfg1 = compose(config_name="config")
# Inner context temporarily overrides
with initialize(version_base=None, config_path="conf2"):
cfg2 = compose(config_name="config")
# Back to outer context
cfg1_again = compose(config_name="config")All initialization methods work with structured configs:
from dataclasses import dataclass
from hydra import initialize, compose
from hydra.core.config_store import ConfigStore
@dataclass
class Config:
name: str = "default"
value: int = 42
# Register structured config
cs = ConfigStore.instance()
cs.store(name="my_config", node=Config)
# Can use any initialization method
with initialize(version_base=None, config_path=None):
cfg = compose(config_name="my_config")
print(f"{cfg.name}: {cfg.value}")Common initialization errors:
from hydra import initialize_config_dir, HydraException
# Relative path error
try:
with initialize_config_dir(version_base=None, config_dir="relative/path"):
pass
except HydraException as e:
print("Must use absolute path")
# Module import error
try:
with initialize_config_module(version_base=None, config_module="nonexistent.module"):
pass
except (ImportError, ModuleNotFoundError) as e:
print("Module not found or not importable")All initialization classes implement the context manager protocol:
# Can be used with explicit enter/exit
init_ctx = initialize(version_base=None, config_path="conf")
init_ctx.__enter__()
try:
cfg = compose(config_name="config")
finally:
init_ctx.__exit__(None, None, None)
# But with statement is recommended
with initialize(version_base=None, config_path="conf"):
cfg = compose(config_name="config")The caller_stack_depth parameter controls path resolution:
def my_init_wrapper():
# Need stack depth 2 to find config relative to calling function
with initialize(
version_base=None,
config_path="conf",
caller_stack_depth=2
):
return compose(config_name="config")
def caller():
# Config path resolved relative to this function
return my_init_wrapper()Control backward compatibility behavior:
# Use current version behavior (recommended)
with initialize(version_base=None, config_path="conf"):
cfg = compose(config_name="config")
# Use Hydra 1.1 compatible behavior
with initialize(version_base="1.1", config_path="conf"):
cfg = compose(config_name="config")Install with Tessl CLI
npx tessl i tessl/pypi-hydra-core