Hydra
Hydra is an open-source Python framework developed by Facebook Research for elegantly configuring complex applications. It enables hierarchical configuration, command-line overrides, multi-run experiments, and dynamic object instantiation. Hydra maintains a regular release cadence with both major and patch versions to introduce new features and address bugs.
Warnings
- breaking Hydra 1.3.2 dropped support for Python 3.6. Applications running on Python 3.6 will not be able to upgrade to this or newer versions of Hydra.
- breaking The default composition order of the Defaults List changed significantly in Hydra 1.1. In Hydra 1.0, configs from the defaults list would override the primary config, but in 1.1 and later, the primary config overrides configs from the defaults list. This requires explicit use of the `_self_` keyword.
- breaking Hydra 1.1 introduced recursive defaults lists and recursive instantiation, which changed how configurations are composed and objects are created. Upgrading from 1.0 to 1.1 requires careful review of the changes, especially regarding `OmegaConf` 2.1 compatibility.
- gotcha The `version_base` parameter in `@hydra.main` should be explicitly set (e.g., `version_base='1.3'` or `version_base=None`). Not setting it can lead to backward compatibility warnings or unexpected behavior in future Hydra versions.
- gotcha When `hydra.job.chdir=True` (which became `False` by default in v1.2), Hydra changes the current working directory to the job's output directory. Using `os.getcwd()` will then return this new directory, not where your script was launched. This can cause issues with relative file paths.
- gotcha Hydra has a tight dependency on specific versions of `OmegaConf`. Incompatible `OmegaConf` versions can lead to installation failures or runtime errors. For instance, Hydra 1.3.1 specifically relaxed its pin to allow `OmegaConf` 2.3.
Install
-
pip install hydra-core --upgrade
Imports
- hydra
import hydra
- DictConfig, OmegaConf
from omegaconf import DictConfig, OmegaConf
- instantiate
from hydra.utils import instantiate
- get_original_cwd
from hydra.utils import get_original_cwd
- HydraConfig
from hydra.core.hydra_config import HydraConfig
Quickstart
import hydra
from omegaconf import DictConfig, OmegaConf
import os
# Create a config directory and file (e.g., conf/config.yaml)
# In a real project, this would be a file on disk.
# For this example, we simulate it.
# Make sure to run `mkdir -p conf` first if running directly.
config_content = """
app:
name: MyHydraApp
version: 1.0.0
db:
driver: mysql
user: ${oc.env:DB_USER, omry}
password: ${oc.env:DB_PASSWORD, secret}
"""
# Create a dummy config file for the quickstart to be runnable
# In a typical setup, 'conf/config.yaml' would exist beforehand.
if not os.path.exists('conf'):
os.makedirs('conf')
with open('conf/config.yaml', 'w') as f:
f.write(config_content)
@hydra.main(version_base="1.3", config_path="conf", config_name="config")
def my_app(cfg: DictConfig) -> None:
print(f"Application Name: {cfg.app.name}")
print(f"Database Driver: {cfg.db.driver}")
print(f"Database User: {cfg.db.user}")
print(f"Database Password: {cfg.db.password}")
print(f"Original Working Directory: {hydra.utils.get_original_cwd()}")
print(f"Current Working Directory: {os.getcwd()}")
print(OmegaConf.to_yaml(cfg))
if __name__ == "__main__":
# Set environment variables for demonstration if not already set
os.environ['DB_USER'] = os.environ.get('DB_USER', 'my_db_user')
os.environ['DB_PASSWORD'] = os.environ.get('DB_PASSWORD', 'my_db_pass')
my_app()
# Clean up the dummy config file for repeated runs
os.remove('conf/config.yaml')
os.rmdir('conf')