20

假设我们有以下设置(从Hydra 文档复制并缩短):

配置文件:config.yaml

db:
  driver: mysql
  user: omry
  pass: secret

蟒蛇文件:my_app.py

import hydra
@hydra.main(config_path="config.yaml")
def my_app(cfg):
    print(cfg.pretty())
if __name__ == "__main__":
    my_app()

当我们可以在函数上使用装饰器时,这很有效my_app。现在我想(对于小脚本和测试目的,但这并不重要)cfg在任何函数之外获取这个对象,只是在一个普通的 python 脚本中。据我了解装饰器的工作原理,应该可以调用

import hydra
cfg = hydra.main(config_path="config.yaml")(lambda x: x)()
print(cfg.pretty())

但 thencfg只是None而不是所需的配置对象。所以看起来装饰器没有传递返回的值。还有其他方法可以做到cfg吗?

4

5 回答 5

24

使用撰写 API

from hydra import compose, initialize
from omegaconf import OmegaConf

initialize(config_path="conf", job_name="test_app")
cfg = compose(config_name="config", overrides=["db=mysql", "db.user=me"])
print(OmegaConf.to_yaml(cfg))

这只会构成配置,不会产生更改工作目录或配置 Python 日志系统等副作用。

于 2020-04-12T10:04:10.617 回答
5

以上解决方案都不适合我。他们给出了错误:

“builtin_function_or_method”对象没有属性“代码

GlobalHydra 已经初始化,如果要重新初始化,请调用 Globalhydra.instance().clear()

我进一步研究了 hydra 并意识到我可以使用 OmegaConf 直接加载文件。你没有得到覆盖,但我对此并不大惊小怪。

import omegaconf
cfg = omegaconf.OmegaConf.load(path)
于 2021-02-23T10:40:15.717 回答
0

我找到了一个相当丑陋的答案,但它有效 - 如果有人找到更优雅的解决方案,请告诉我们!

我们可以使用闭包或一些可变对象。在此示例中,我们在外部定义一个列表并附加配置对象:

import hydra
c = []
hydra.main(config_path="config.yaml")(c.append)()
cfg = c[0]
print(cfg.pretty())
于 2020-03-13T16:49:07.010 回答
0

另一个丑陋的答案,但作者说这可能会在下一个版本中被迷恋

块引用

from omegaconf import DictConfig
from hydra.utils import instantiate
from hydra._internal.utils import _strict_mode_strategy, split_config_path, create_automatic_config_search_path
from hydra._internal.hydra import Hydra
from hydra.utils import get_class 

class SomeThing:
...
def load_from_yaml(self, config_path, strict=True):
    config_dir, config_file = split_config_path(config_path)
    strict = _strict_mode_strategy(strict, config_file)
    search_path = create_automatic_config_search_path(
        config_file, None, config_dir
    )
    hydra = Hydra.create_main_hydra2(
        task_name='sdfs', config_search_path=search_path, strict=strict
    )
    config = hydra.compose_config(config_file, [])
    config.pop('hydra')
    self.config = config
    print(self.config.pretty())
于 2020-05-28T08:38:39.383 回答
0

这是我的解决方案

from omegaconf import OmegaConf

class MakeObj(object):
    """ dictionary to object. 
    Thanks to https://stackoverflow.com/questions/1305532/convert-nested-python-dict-to-object

    Args:
        object ([type]): [description]
    """
    def __init__(self, d):
        for a, b in d.items():
            if isinstance(b, (list, tuple)):
                setattr(self, a, [MakeObj(x) if isinstance(x, dict) else x for x in b])
            else:
                setattr(self, a, MakeObj(b) if isinstance(b, dict) else b)


def read_yaml(path):
    x_dict =  OmegaConf.load(path)
    x_yamlstr = OmegaConf.to_yaml(x_dict)
    x_obj = MakeObj(x_dict)
    return x_yamlstr, x_dict, x_obj
    
x_yamlstr, x_dict, x_obj = read_yaml('config/train.yaml')
print(x_yamlstr)
print(x_dict)
print(x_obj)
print(dir(x_obj))
               
于 2022-01-18T08:50:52.397 回答