Hydra是一个用来动态创建配置的python开源框架,使做研究和复杂的应用更便利,配置信息可以通过配置文件或者运行参数来覆盖。Hydra的名字来源于其可以运行多个相似任务,就像Hydra(九头蛇)有多个头一样。
稳定版:
pip install hydra-core --upgrade
可以安装以前的版本,但是可能包含bug,并且可能和现有的插件不兼容。
pip install hydra-core --pre --upgrade
配置文件config.yaml内容:
db:
driver:mysql
user:omry
pass:secret
python文件:
import hydra
@hydra.main("config.yaml") # 未指定路径时是当前文档的路径
def test(conf):
print(config)
if __name__=='__main__':
test() # 不传参数,由hydra对参数进行注入
如果每次都使用命令行参数那就很奇怪了。可以通过创建配置文件来配置参数。
配置文件config.yaml:
db:
driver: mysql
user: omry
pass: secret
通过给@hydra.main()
装饰器函数传入一个config_path
来指定参数文件:
@hydra.main(config_path="conf/config.yaml")
def test(cfg):
print(cfg.pretty())
config.yaml
会在你运行应用程序的时候自动加载。可以通过命令行输入的参数来对配置文件中的参数进行覆盖。
strict mode
无论是在命令行参数覆盖还是早期编码的时候都非常有用。当你给config_path
指定了配置文件的时候,默认是使用strict mode
的。如果试图从配置文件中获取一个不存在的配置项时,会报KeyError
。
通过strict mode
也可以捕获在使用命令行参数覆盖配置文件时的异常。如果试图覆盖一个配置文件中不存在的key时,也会抛出异常。
如果将strict mode
关闭,获取不存在的key是允许的。
@hydra.main(config_path="conf/config.yaml",strict=False)
配置组是Hydra中最重要的概念。
假如你想在程序中使用PG和Mysql。程序运行的时候,要么用PG,要么用Mysql,但不会同时用。要通过Hydra来实现的话就需要用到配置组。配置组就是互斥的配置文件集合。
要创建一个配置组,创建一个db
文件夹,文件下为每种数据库准备了一个配置文件。同时,因为我们还希望拥有多个配置组,所以我们将所有配置文件都放在conf
目录下。
config_path
可以指定配置文件,也可以指定配置文件的根目录。如果指定的是某个配置文件,那么这个配置文件的位置就在根目录。
我们应用的总体目录文件结构:
|--conf
|----db
|------pg.yaml
|------mysql.yaml
|--main.py
pg.yaml
:
db:
driver: pg
pass: secretpg
mysql.yaml
:
db:
driver: pg
pass:secretpg
main.py
:
@hydra.main(config_path="conf")
def test(cfg):
print(cfg.pretty())
print(cfg.db.driver)
if __name__ == "__main__":
test()
这时,如果执行执行程序我们拿到的配置项会是空字典{}
,因为我们还没有指定db这个配置组使用哪一份配置文件。需要用python main.py db=mysql
来指定db
选用那份配置文件。同时在运行时也可以动态覆盖配置项python main.py db=mysql db.pass=test1
。
上面的例子证明了Hydra的一个强大的特性:你可以用多个配置文件来组织你的配置对象。
假如你需要默认使用mysql作为数据库,你又不想每次运行程序的时候通过命令行的方式来设置db=mysql
。可以在配置文件中添加一系列默认值defaults
。
配置文件config.yaml
:
defaults:
- db: mysql
记得将config_path
的值指定为config.yaml
:
@hydra.main(config_path="conf/config.yaml")
def test(cfg):
print(cfg.pretty())
当你运行程序的时候,就会默认将db
设置为mysql。
可以在运行程序的时候通过命令行指定来覆盖单独的配置组或者配置组中的某个具体的值。
同时,也可以将某个配置组设置为null
来避免加载任何一个配置组。
有时候你想合并的一个配置文件并不属于任何配置组,比如test.yaml。那么你可以在defaults
中指定这个配置文件,程序运行时也会加载该配置文件。
defaults:
- test.yaml
- groups=XXX
有时候你希望将程序在各种可能得配置组组合上都运行一次,要达到这样的效果,用--multirun(-m)
标记,并且在各个维度上都传递一个用逗号分隔的列表。
默认的启动器在本地顺序运行各种配置组的组合。运行代码如下:
python /opt/scripts/hydra/main.py db=mysql,pg -m
如果你需要为程序每次执行都指定一个新目录,Hydra通过为程序的每次运行都创建一个新目录,并在此目录中执行你的代码来实现。
工作目录(working directory)用来:
如果需要的话,你仍然可以获取原始工作目录(程序所在的目录)
import hydra
import os
from hydra import utils
@hydra.main(config_path="conf/config.yaml")
def test(cfg):
print("current working directory {}".format(os.getcwd()))
print("original working directory {}".format(utils.get_original_cwd()))
由于启动代价较大,一般不会使用python的logging。Hydra通过配置python logging来为你解决。Hydra默认对命令行和文件都使用INFO
级别的日志。
import hydra
import os
from hydra import utils
import logging
logger=logging.getLogger(__name__)
@hydra.main(config_path="conf/config.yaml")
def test(cfg):
logger.info(os.getcwd())
logger.warning(utils.get_original_cwd())
你可以通过用命令行参数的方式来覆盖hydra.verbose
来将你的日志级别设置为DEBUG
。
hydra.verbose
可以是一个布尔型、字符串、或者是一个列表:
hydra.verbose=true
,将所有日志的级别设置为DEBUG
hydra.verbose=__main__
,将__main__
的日志级别实质为DEBUG
hydra.verbose=[__main__,hydra]
,将__main__和hydra的日志级别设置为DEBUG
Hydra提供了一些增强可调试性的选项。
通过命令行添加-c job
或者--cfg job
来打印参数,而不是实际运行程序。
/opt/anaconda3/bin/python /opt/scripts/hydra/main.py -c job
db:
driver: mysql
pass: secretmysql
view:
front: elasticsearch
打印出来的配置参数是任务实际执行时接收的参数。--cfg
选项会接受一个用来表示要打印哪部分的参数: