Hydra
1. 介绍:
Hydra 能通过解析和覆写
config
文件和command
命令动态构建多层次配置。
- 可以从多个来源组合的分层配置
- 可以从命令行指定或覆盖配置
- 动态命令行选项卡完成
- 在本地运行您的应用程序或启动它以远程运行
- 使用单个命令以不同的参数运行多个作业
# config.yaml
db:
driver: mysql
user: omry
pass: secret
# my_app.py
import hydra
from omegaconf import DictConfig, OmegaConf
@hydra.main(config_name="config")
def my_app(cfg : DictConfig) -> None:
print(OmegaConf.to_yaml(cfg))
if __name__ == "__main__":
my_app()
# 运行程序
$ python my_app.py
>>> db:
driver: mysql
pass: secret
user: omry
# 从命令行获取覆盖内容
$ python my_app.py db.user=root db.pass=1234
>>> db:
driver: mysql
user: root
pass: 1234
2. 组成
用户可能要在不同的数据库之间切换,为了支持这一选择,需要构建
config group
命名db
# 文件集
├── db
│ ├── mysql.yaml
│ └── postgresql.yaml
├── config.yaml
└── my_app.py
# 新的 config.yaml
defaults:
-db: mysql
default
会直接告诉 Hydra
,当组合configuration时,使用 db/mysql.yaml
3. Multirun
通过
--multirun | -m
选择不同的配置
4. 应用
# my_app.py
from omegaconf import DictConfig, OmegaConf
import hydra
@hydra.main()
def my_app(cfg: DictConfig) -> None:
print(OmegaConf.to_yaml(cfg))
if __name__ == "__main__":
my_app()
本例中,Hydra 构造了一个空的 cfg
实例,然后使用 @hydra.main
传入函数中,也可以通过命令行使用 +
添加config的值,如:
$ python my_app.py +db.driver=mysql +db.user=omry +db.password=secret
db:
driver: mysql
user: omry
password: secret
-
Example
通过
config_name
参数传递给@hydra.main()
,但是要忽略.yaml
后缀,这样config.yaml
就会在运行my_app()
时载入。# my_app.py @hydra.main(config_name='config') def my_app(cfg): print(OmegaConf.to_yaml(cfg))
-
使用
config object
——Omegaconf
- 空实例
>>> from omegaconf import OmegaConf >>> conf = OmegaConf.create() >>> print(OmegaConf.to_yaml(conf)) {}
- From
dictionary
>>> conf = OmegaConf.create({"k" : "v", "list" : [1, {"a": "1", "b": "2", 3: "c"}]}) >>> print(OmegaConf.to_yaml(conf)) k: v list: - 1 - a: '1' b: '2' 3: c
- From
list
>>> conf = OmegaConf.create([1, {"a":10, "b": {"a":10, 123: "int_key"}}]) >>> print(OmegaConf.to_yaml(conf)) - 1 - a: 10 b: a: 10 123: int_key
- From yaml file
>>> conf = OmegaConf.load('source/example.yaml') >>> # Output is identical to the YAML file >>> print(OmegaConf.to_yaml(conf))
- From dot-list
>>> dot_list = ["a.aa.aaa=1", "a.aa.bbb=2", "a.bb.aaa=3", "a.bb.bbb=4"] >>> conf = OmegaConf.from_dotlist(dot_list) >>> print(OmegaConf.to_yaml(conf)) a: aa: aaa: 1 bbb: 2 bb: aaa: 3 bbb: 4
-
config 文件组
# 文件树 ├── conf │ └── db │ ├── mysql.yaml │ └── postgresql.yaml └── my_app.py # db/mysql.yaml # @package _group_ driver: mysql user: omry password: secret
1)现在执行
my_app.py
获取的是空的config$ python my_app.py {}
2)可以添加配置文件
$ python my_app.py +db=postgresql db: driver: postgresql pass: drowssap timeout: 10 user: postgres_user
-
从 config 分组中选择
defaults
# config.yaml defaults: - db: mysql # 代码 @hydra.main(config_path="conf", config_name="config") def my_app(cfg: DictConfig) -> None: print(OmegaConf.to_yaml(cfg))
# 文件树 ├── conf │ ├── config.yaml │ ├── db │ │ ├── mysql.yaml │ │ └── postgresql.yaml │ ├── schema │ │ ├── school.yaml | │ ├── support.yaml │ │ └── warehouse.yaml │ └── ui │ ├── full.yaml │ └── view.yaml └── my_app.py
# config.yaml defaults: - db: mysql - ui: full - schema: school
输出:
$ python my_app.py db: driver: mysql user: omry pass: secret ui: windows: create_db: true view: true schema: database: school tables: - name: students fields: - name: string - class: int - name: exams fields: - profession: string - time: data - class: int
5. 运行 Hydra
1)Output/Working 目录
Hydra 解决了每次执行时需要自己建立输出目录。 Hydra 会在工作目录下对每次执行创建一个目录。
import os
from omegaconf import DictConfig
@hydra.main()
def my_app(cfg: DictConfig) -> None:
print("Working directory : {}".format(os.getcwd()))
$ python my_app.py
Working directory : /home/omry/dev/hydra/outputs/2019-09-25/15-16-17
$ python my_app.py
Working directory : /home/omry/dev/hydra/outputs/2019-09-25/15-16-19