0

我希望这里有人可以帮助我,因为我是 Hydra 配置框架的新手。

假设我们有一个具有这种结构的 Python 项目:

hydra_config
├── conf
│   ├── api_key
│   │   ├── non_prod.yaml
│   │   └── prod.yaml
│   └── db
│       ├── mysql.yaml
│       └── postgresql.yaml
├── modules
│   └── module.py
└── my_app.py

现在,在 Hydra 的配置文档中,他们声明我们需要在我们想要访问配置文件的函数之上添加一个 Python 装饰器。但是,文档仅显示了如何对my_app.py作为项目主要模块的函数执行此操作。

问题是,如何添加

@hydra.main(config_path="conf")

一个函数的 Python 装饰器,假设module_function它位于modules/module.py? 以下是 的内容module.py

import hydra
from omegaconf import DictConfig, OmegaConf

@hydra.main(config_path="conf")
def module_function(cfg: DictConfig):
    print(OmegaConf.to_yaml(cfg))

然后下面是主要 Python 模块的内容my_app.py

from modules.module import module_function

def main():
    module_function()

if __name__ == "__main__":
    main()

当我尝试使用 运行主要 Python 模块my_app.pypython my_app.py,我立即收到一条错误消息

Primary config module 'modules.conf' not found.
Check that it's correct and contains an __init__.py file

Set the environment variable HYDRA_FULL_ERROR=1 for a complete stack trace.

我知道这意味着添加到module_function里面的装饰器module.py找不到conf包含api_keydb配置组的目录。

这里有没有人有这方面的经验并且知道如何解决这个错误?

任何帮助将不胜感激。谢谢!

4

1 回答 1

0

首先我会介绍一些可能的解决方案,然后我会给出解释。以下是您可以做的三件事来使您的示例工作:

修复 1:创建conf/__init__.py并更改config_path="conf"config_path="../conf"
├── conf
│   ├── config.yaml
│   └── __init__.py
├── modules
│   └── module.py
└── my_app.py
# modules/module.py
import hydra
from omegaconf import DictConfig, OmegaConf

@hydra.main(config_path="../conf", config_name="config")  # relative path
def module_function(cfg: DictConfig):
    print(OmegaConf.to_yaml(cfg))
修复 2:移动confmodules/conf并创建modules/conf/__init__.py
├── modules
│   ├── conf
│   │   ├── config.yaml
│   │   └── __init__.py
│   └── module.py
└── my_app.py
修复 3:在模块中定义您的装饰函数,该函数将被称为__main__
├── conf
│   └── config.yaml
└── my_app.py
# my_app.py
import hydra
from omegaconf import DictConfig, OmegaConf

@hydra.main(config_path="conf", config_name="config")
def module_function(cfg: DictConfig):
    print(OmegaConf.to_yaml(cfg))

if __name__ == "__main__":
    module_function()

修复 3 不会让 OP 非常满意 :)

解释

在您的示例中,由于您已导入修饰函数(而不是在__main__模块中定义它),Hydra 将参数解释config_path="conf"为相对于定义修饰函数的模块的父级。在您的示例中,装饰函数定义在 中modules.module,其父级是modules,因此 Hydra 正在寻找一个名为modules.conf. 如果找到,将在此包中搜索 yaml 文件。

上面的修复 2 采用了确保modules/conf/__init__.py存在的方法,因此它modules.conf实际上是一个 python 包。同时,Fix 1 采用了相对路径的方式config_path="../conf"。Hydra 然后寻找一个名为conf. 由于存在,因此找到并搜索conf/__init__.py此顶级包以查找 yaml 文件。conf为了发现这个包,Hydra 使用了 python 导入机制。这意味着 Hydra 能够发现位于您其他地方的 python 包中的 yaml 文件,$PYTHONPATH或者通过包管理器(例如pip.

在 Fix 3 的情况下,我们有module_function.__module__ == "__main__",这意味着 Hydra 不能依赖 python 的导入机制来发现module_function定义的位置。作为后备,Hydra 尝试查找目录 conf(而不是 conf);这就是__init__.py修复 3 不需要文件的原因。以下是实现此行为的关键代码行。请注意,conf它仍然被视为相对路径,相对于包含定义修饰函数的文件的目录(而不是定义它的模块的父级)。是实现此相对路径计算的函数(对于模块情况和目录情况)。

于 2022-01-31T08:33:08.950 回答