Config as Python
Config as Python
Tutorial: Why Laco?See also: Lie-Typing, API: laco.load
Why Python Files?
Traditional config systems use YAML or JSON. Those formats can only represent
primitives, lists, and dicts. Referring to a class like torch.nn.ReLU
requires a magic string ("torch.nn.ReLU") that silently breaks on rename.
Laco config files are real .py files. You get:
- Real imports: if
torch.nn.ReLUis renamed,importfails loudly at load time - IDE go-to-definition, autocomplete, and refactoring on config targets
- Arbitrary Python expressions for derived values
- No separate config DSL to learn
The trade-off: configs are code, so the same discipline applies (version control, code review, reproducibility via pinned deps).
How laco.load Works
cfg = laco.load("configs/mlp.py")
Internally:
- The
.pyfile is read and compiled. - A controlled
execruns the module in a namespace with_patch_importactive, so relative imports within config packages resolve correctly. - Names in
__all__(or all non-underscore names if__all__is absent) are exported as keys in aDictConfig. - Each exported value is recursively converted:
DictConfignodes are spliced in; primitives are kept; other objects raiseTypeErrorunless they areLazyObjectnodes produced byL.calland friends.
The configs:// Protocol
Laco registers a path handler with expath so that configs:// URLs resolve
against the installed laco.examples package:
cfg = laco.load("configs://examples/mlp.py")
Your own project can register additional configs:// namespaces via the
[project.entry-points.configs] table in pyproject.toml:
[project.entry-points.configs]
my_project = "my_project.configs"
Then laco.load("configs://my_project/train.py") resolves to the
my_project/configs/train.py file inside the installed package.
YAML Round-Trip
cfg = laco.load("configs/mlp.py")
laco.dump(cfg) # → Hydra-compatible YAML string
laco.save(cfg, "run/config.yaml") # → file on disk
cfg2 = laco.load("run/config.yaml") # ← load the YAML back
YAML configs produced by laco.dump include a _laco_: 1 schema-version
marker stripped on load. They are valid Hydra YAML and can be consumed by
any Hydra application.
LoadMode
cfg = laco.load("configs/mlp.py", mode=laco.LoadMode.SAFE)
LoadMode.SAFE removes dangerous builtins (open, eval, exec, …) and
enforces a module allowlist. Use it when loading configs from untrusted
sources. See How-To: Safe Loading.