Skip to content

Hydra 環境配置管理套件筆記

Last Updated on 2023-02-01 by Clay

Introduction

Hydra是一個開源的 Python 框架,它被設計用來簡化研發佈署的流程(尤其是在複雜的應用上)。Hydra 能夠在佈署時動態地建立階層式的設定檔案、也透過命令列(command line)來繼承(複寫)設定檔。

官方紀錄的主要功能如下:

  • 複數來源的階層式設定部屬
  • 可以透過命令列指定、複寫設定
  • 動態命令列補完
  • 可以在本地端或遠端運行應用程式
  • 可以用單行指令執行多個任務

現在的 Hydra 是 1.2 穩定版本,支援 Linux、MacOS、Windows。(2022-12-09)


Quick start

Installation

我們可以透過 pip 套件管理工具進行安裝。

pip3 install hydra-core --upgrade



Basic example

以下是一個基本的 hydra 使用範例,我們真正要執行的程式是 app.py,而 conf 則是我們設定檔所存放的資料夾(後面的範例中,我們會有很多的設定檔)。


資料夾結構

hydra_sample/
├── app.py
└── conf
    └── config.yaml

如果要測試 hydra,你可以製作一個一模一樣的架構。


conf/config.yaml

這是一個 YAML 的設定檔,裡面有一些關於網站的設定。

web:
  web_name: clay-atlas.com
  account: clay
  password: secret


app.py

而我們要執行的程式中,主要執行邏輯必須包含在一個函式中,函式的上方需要添加 hydra 的修飾符 @hydra.main() ,裡面則必須傳入必須的參數。

import hydra
from omegaconf import DictConfig, OmegaConf


@hydra.main(version_base=None, config_path="conf", config_name="config")
def my_app(cfg: DictConfig) -> None:
    print(OmegaConf.to_yaml(cfg))


if __name__ == "__main__":
    my_app()


執行效果

$ python3 app.py
web:
  web_name: clay-atlas.com
  account: clay
  password: secret


如果我們要修改設定檔的參數,我們可以直接在命令列中指令參數的傳入值。例如我在這裡就修改了 accountpassword

python3 app.py web.account=test web.password=1234
web:
  web_name: clay-atlas.com
  account: test
  password: 1234


多個不同的設定檔案

(可以看到,架構變得更複雜了!)

hydra_sample/
├── app.py
└── conf
    ├── config.yaml
    └── db
        ├── web1.yaml
        └── web2.yaml


conf/config.yaml

首先,最上層的設定檔只指定了一個參數:它要讀取 db 底下哪個設定檔

在這裡,我們預設是 web1

defaults:
  - db: web1



conf/db/web1.yaml

web1 中,我們設定了 google 的網站、帳號與密碼。

web_name: www.google.com
account: google
password: 1234



conf/db/web2.yaml

web2 中,我們做了跟 web1 相似的事情,只不過改成了我的個人網站、帳號與密碼。

web_name: clay-atlas.com
account: clay
password: secret



RUN

接下來就是執行的部份了。app.py 仍然沒有任何改動,唯一做的事情就是把參數打印出來。

$ python3 app.py 
db:
web_name: www.google.com
account: google
password: 1234



可以看到,我們預設的參數就是 google 那一組參數設定!如果我們想要改成另外一組參數設定,我們就直接把 db=web2 寫在執行檔案的命令列中。

$ python3 app.py db=web2


Output:

db:
  web_name: clay-atlas.com
  account: clay
  password: secret


除了設定 db 要吃哪個設定檔外,我們也可以直接指定 db 底下的參數哦。

$ python3 app.py db=web2 db.password=9999


Outputs:

db:
  web_name: clay-atlas.com
  account: clay
  password: 9999


以上是一些 Hydra 的基本用法。包含如何寫設定檔、如何在命令列中改動參數。


我們可以使用 "+" 在命令列執行過程中添加參數

以下的程式,Hydra預設建立一個空的 cfg 物件並傳遞給 @hydra.main() 裝飾的函式。
我們可以在命令列執行程式時,動態地使用 + 來添加參數。

這跟在命令列中指定參數不同,我們添加的參數可以是從未在設定檔中出現的參數。

from omegaconf import DictConfig, OmegaConf
import hydra


@hydra.main(version_base=None)
def my_app(cfg: DictConfig) -> None:
    print(OmegaConf.to_yaml(cfg))


if __name__ == "__main__":
    my_app()


執行:

python3 app.py +arg1=111 +arg2=222


Outputs:

arg1: 111
arg2: 222

指定一個設定檔(config file)

我們可以透過在 hydra.main() 中傳遞 config_path 和 config_name 來指定要讀取的設定檔路徑。

  • config_path: 設定檔所在的位置(通常為設定檔所在的資料夾位置)
  • config_name: 設定檔的名稱
from omegaconf import DictConfig, OmegaConf
import hydra


@hydra.main(version_base=None, config_path=".", config_name="config")
def my_app(cfg: DictConfig) -> None:
    print(OmegaConf.to_yaml(cfg))


if __name__ == "__main__":
    my_app()


像以上的範例程式,讀取的設定檔就是在當前目錄底下,名為 config.yaml 的檔案。

當然,我們同樣可以使用 + 來添加參數

python3 app.py +arg3=333


如果參數已經存在於設定檔中,我們可以直接覆寫該參數

python3 app.py arg2=333


如果參數存在於設定檔中則覆寫,如不存在則直接新增。此功能可以使用 ++ 來做到

python3 app.py ++arg4=444

我們可以使用屬性(attribute)和字典(dictionary)的方式來存取變數

from omegaconf import DictConfig, OmegaConf
import hydra


@hydra.main(version_base=None, config_path="conf", config_name="config")
def my_app(cfg: DictConfig) -> None:
    print(cfg.node.arg1)
    print(cfg["node"]["arg1"])


if __name__ == "__main__":
    my_app()


我們可以設定預設配置組合

原本直接執行的結果會是以下的參數被打印出。

python3 app.py


Output:

db:
  web_name: www.google.com
  account: google
  password: 1234


當然,如果我們不再需要使用這個參數,也可以透過命令列移除預設配置組合。

python3 app.py ~db


Output:

{}

如果我們的預設配置中,包含著固定的配置組合、以及我們想預設的非配置組合參數

比方說我們知道我們的 db 需要使用幾乎所有的 web1 固定配置組合。

然而,account 我們也知道需要更改成 **BERT**

這種時候,我們要為了僅僅一個參數另外新增一個固定的組合配置 web3 嗎?

實際上,我們可以設定 _self_ 在 defaults 底下,然後另外配置我們所需要的客製化參數。

config.yaml

defaults:
  - db: web1
  - _self_

db:
  account: BERT


然後執行:

python3 app.py


Output:

db:
  web_name: www.google.com
  account: BERT
  password: 1234


到這裡,常用的 Hydra 功能應該已經介紹完畢了。如果還有待挖掘的好用功能,或許只要在我遇過實際案例後才會明白了。


References


Read More

Leave a Reply