ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Hydra 教程:用 Defaults List 为复杂应用设定默认配置

Hydra 教程:用 Defaults List 为复杂应用设定默认配置 Hydra 教程用 Defaults List 为复杂应用设定默认配置【免费下载链接】hydraHydra is a framework for elegantly configuring complex applications项目地址: https://gitcode.com/GitHub_Trending/hyd/hydra导读本文聚焦 Hydra 教程Defaults默认配置这一核心主题在完成了 Config Group配置组 的学习之后如何通过在主配置文件中声明defaults列表让应用默认加载某个配置组选项从而省去每次运行时手动敲击dbmysql的麻烦。读完本文你将掌握 defaults 列表的基本语法、命令行覆盖与删除默认项的方法、非配置组默认文件的加载规则以及 defaults 列表在 Hydra 底层defaults_list.py是如何被解析与合成的。1. 背景从 Config Group 说起在正式介绍 defaults 之前先回顾一下它的前身概念——配置组Config Group。配置组是一组互斥的配置文件。以数据库为例在conf目录下创建db子目录为每个备选数据库各放一个 YAML 文件├── conf │ └── db │ ├── mysql.yaml │ └── postgresql.yaml └── my_app.py其中 mysql.yaml 与 postgresql.yaml 各描述一种数据库连接配置。应用启动时通过命令行显式指定用哪一个$ python my_app.py dbpostgresql db: driver: postgresql pass: drowssap timeout: 10 user: postgres_user问题在于每次运行都要敲dbmysql非常繁琐。而defaults列表正是为了解决默认加载哪一份配置而生的。2. Config Group 默认项在配置文件中声明 defaults 列表假设经过讨论团队决定默认使用 MySQL。只需要在config.yaml中增加一个defaults列表defaults: - db: mysql注意这里db: mysql是Group Defaultdb是配置组名mysql是该配置组中的某个选项。它表示从db配置组中选择mysql这份配置作为默认值。同时需要把config.yaml指定为config_path在 Hydra 1.0 及更早版本中config_path可以直接指向配置文件hydra.main(config_pathconf/config.yaml) def my_app(cfg): print(OmegaConf.to_yaml(cfg))现代版本的等价写法是拆分成config_path与config_name两个参数仓库中的实际示例 5_defaults/my_app.py 正是如此from omegaconf import DictConfig, OmegaConf import hydra hydra.main(config_pathconf, config_nameconfig) def my_app(cfg: DictConfig) - None: print(OmegaConf.to_yaml(cfg)) if __name__ __main__: my_app()现在直接运行应用无需任何参数MySQL 配置就会被默认加载$ python my_app.py db: driver: mysql pass: secret user: omry也就是说defaults: - db: mysql等效于在命令行里手动敲dbmysql但它是声明在配置里、无需每次重复输入的。对应的两份候选配置内容见 5_defaults/conf/db/mysql.yaml 与 5_defaults/conf/db/postgresql.yaml。2.1 defaults 列表可以有多个条目defaults 列表不限于一个条目可以同时声明多个默认项例如教程进阶示例 6_composition/conf/config.yamldefaults: - db: mysql - ui: full - schema: school从源码结构看这种写法实际上告诉 Hydra最终配置对象由db、ui、schema三个配置组中的指定选项合成而来——这正是 Hydra 将多个配置文件组合成一个配置对象的核心能力详见同目录 6_composition 的完整示例。2.2 组合顺序规则多个 defaults 条目的合成遵循两条顺序规则如果多个配置定义了同一个值后出现的条目胜出last one wins如果多个配置向同一个字典贡献内容结果是这些字典的合并。此外如果你的主配置文件自身也包含普通配置值则需要注意主配置与 defaults 条目的合并顺序Hydra 默认会把主配置文件_self_追加到 defaults 列表末尾因此主配置可以覆盖 defaults 中配置的值。如果希望反过来让 defaults 覆盖主配置可以显式把_self_写在 defaults 列表第一项详见下文第 6 节。3. 覆盖配置组默认项声明了默认配置并不意味着失去了灵活性。你依然可以在命令行里覆盖默认值甚至可以顺便覆盖具体字段$ python my_app.py dbpostgresql db.timeout20 db: driver: postgresql pass: drowssap timeout: 20 user: postgres_user这里发生了两件事dbpostgresql把 defaults 列表中db组的选项从默认的mysql替换为postgresqldb.timeout20在合成后的配置上覆盖了timeout字段——注意mysql.yaml里并没有timeout字段postgresql.yaml默认是timeout: 10最终被命令行覆盖为20。在 Hydra 的解析流程中这种命令行覆盖优先的规则是有明确实现的。查看 defaults_list.py 中的Overrides.__init__可以看到命令行覆盖会被记录进override_choices第 109-111 行并且带external_overrideTrue标记而随后的override_default_option()第 141-147 行会把被选中的 Group Default 的值替换为命令行指定的选项。注释中也写得很清楚外部命令行覆盖在遍历开始前就已注册因此永远拥有最高优先级第 116-119 行。更细节的行为是如果你在命令行覆盖了某个db组但 defaults 列表里根本不存在该组Hydra 会抛出ConfigCompositionException并提示Did you mean to override one of ...第 166-194 行避免你因为拼错组名而静默得到空配置。4. 用 null 阻止默认配置加载有些场景下你可能希望这次运行什么都不加载这个默认项。只需在命令行把该配置组赋值为null$ python my_app.py dbnull {}输出变成了空字典{}说明db组的默认项被完全移除了最终合成的配置中没有任何内容。这与 Hydra 在 defaults 列表语法中对null的定义一致——null是为未来覆盖预留的占位符如果它没有被覆盖该条目就会被忽略详见 advanced/defaults_list.md 对OPTION语法的说明。需要说明的是删除默认项这一能力在后续 Hydra 版本中演化出了更显式的写法在现代文档中等价操作是使用~前缀即python my_app.py ~db见 5_defaults.md 的现行描述。在 0.11 版本教程中dbnull就是官方推荐的写法。从 defaults_list.py 的实现可以看到这两者最终都会走Deletion逻辑第 30-33 行、第 74-87 行并在is_deleted()第 221-234 行中被识别为删除某个配置组默认项随后在ensure_deletions_used()第 196-201 行中校验如果删除目标在 defaults 列表中不存在会直接报错。5. 非配置组默认项有时你想默认合并的某个配置文件并不属于任何配置组。例如配置文件目录下有一个独立的some_file.yaml只需在 defaults 列表中直接写文件名不带.yaml后缀defaults: - some_fileHydra 会从配置目录中加载some_file.yaml并合并进最终配置。这与配置组默认项有一个关键区别不属于任何配置组的配置文件无法被覆盖。它们总是会被加载。因此官方教程的建议是优先使用配置组。配置组带来的可在命令行切换选项、可被覆盖、可被删除的灵活性是非配置组默认项不具备的。如果某个配置以后可能需要在不同场景间切换把它放进配置组是更稳妥的设计。6. 主配置文件的组合顺序_self_前文 2.2 节提到当主配置文件primary config自身既有配置值、又有 defaults 列表时需要控制主配置内容相对于 defaults 条目的合并顺序方法是在 defaults 列表中显式使用_self_关键字_self_放在列表末尾主配置文件的值会覆盖 defaults 中配置的值defaults: - db: mysql - _self_ db: user: root结果db.user来自主配置config.yamlroot其余字段来自db/mysql.yaml。_self_放在列表第一项defaults 中配置的值会覆盖主配置文件里的同名值defaults: - _self_ - db: mysql db: user: root结果db.user来自db/mysql.yamlomry主配置里的root被覆盖。如果省略_self_Hydra 会自动把它追加到 defaults 列表末尾即默认情况下主配置文件拥有最高优先级。这一点在 defaults_list.py 的_validate_self()第 255-275 行中有直接体现当一个 defaults 列表中没有显式_self_时实现会自动追加ConfigDefault(path_self_)同时如果出现重复的_self_会抛出Duplicateself错误。7. 源码视角defaults 列表如何变成最终配置读完上面的用法再看一眼底层实现会让理解更扎实。Hydra 的配置合成核心位于 hydra/_internal/defaults_list.py整体流程大致如下解析命令行覆盖Overrides.__init__()第 57-111 行遍历命令行传入的 override将其分类为覆盖某个配置组选项override_choices、追加新的默认项append_group_defaults、删除某个默认项deletions或普通字段覆盖config_overrides。构建 defaults 树_create_defaults_tree_impl()第 562-720 行从主配置出发深度优先地展开每个 defaults 条目。_expand_virtual_root()第 288-319 行会先把hydra/config与主配置挂到虚拟根节点之下然后逐层递归每个 Group Default 会继续展开它自己的 defaults 列表从而形成一棵树。应用覆盖遍历过程中overrides.is_overridden()与overrides.override_default_option()负责把命令行指定的选项替换到对应节点上被null或~删除的节点则被标记为deleted。拍平成有序列表_tree_to_list()第 774-796 行用深度优先遍历把 defaults 树拍平成最终的配置加载顺序ensure_no_duplicates_in_list()第 816-827 行还会检查是否有配置组在最终列表中重复出现。错误校验ensure_overrides_used()与ensure_deletions_used()确保每个命令行覆盖/删除都真正命中了一个 defaults 条目否则抛出ConfigCompositionException。正是这棵defaults 树 深度优先遍历的设计支撑起了配置组默认值、命令行覆盖、null 删除、非配置组文件加载等全部功能。想深入了解 defaults 列表的全部语法override关键字、optional关键字、package语法、插值等可以继续阅读仓库中的 advanced/defaults_list.md。8. 动手实践完整可运行示例仓库中 examples/tutorials/basic/your_first_hydra_app/5_defaults 提供了与本文配套的完整示例结构如下5_defaults/ ├── conf │ ├── db │ │ ├── mysql │ │ │ └── engine │ │ │ └── innodb.yaml │ │ ├── mysql.yaml │ │ └── postgresql.yaml │ ├── __init__.py │ └── config.yaml └── my_app.py你可以依次尝试以下操作来验证本文的每个知识点# 1. 默认加载 mysql python my_app.py # 2. 覆盖为 postgresql并覆盖 timeout 字段 python my_app.py dbpostgresql db.timeout20 # 3. 用 null 阻止默认项加载 python my_app.py dbnull如果愿意继续深入6_composition 展示了db、ui、schema三个配置组如何通过 defaults 列表组合成一个完整配置对象是理解Hydra 从多个配置文件中组合配置的最佳下一步练习。小结本文围绕 Hydra 的Defaults List讲解了四个核心能力场景写法效果设定配置组默认项defaults: - db: mysql无需命令行参数即可默认加载 mysql命令行覆盖默认项python my_app.py dbpostgresql切换到 postgresql可叠加字段覆盖阻止默认项加载python my_app.py dbnull现代写法~db移除该默认项得到空配置加载非配置组文件defaults: - some_file无条件合并不可覆盖配合 defaults_list.py 中的Overrides、_create_defaults_tree_impl、_tree_to_list等实现以及 5_defaults 示例目录你已经掌握了 Hydra 配置组默认加载机制的完整脉络——这正是后续学习多配置组合composition的基础。【免费下载链接】hydraHydra is a framework for elegantly configuring complex applications项目地址: https://gitcode.com/GitHub_Trending/hyd/hydra创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表