[Python] yaml 설정에서 {{...}} 변수 이용해 보기 Develop Tip

Python 개발자로서 JSON과 YAML에 대해서 공부를 하다 보면,

json과 yaml 은 모두 동일하게 파이썬의 dict 로 1:1 매핑이되는 객체이기 
때문에 JSON과 YAML이 동일하게 느껴지기는 하지만,
가장 큰 차이점은 YAML이 JSON 보다 훨씬 사람이 보고 읽기에
편하고 코맨트도 쉽게 달 수 있다는 차이점 때문에 
이제는 설정에 관련된 설정파일을 이용할 때 YAML을 많이 이용합니다.

그런데 config에서 다음과 같은 요구가 있을 수 있습니다.

---
server: 10.211.55.29

check_agent_sec: 10
check_agent_update_sec: 3600
check_agent_update_json: http://{{server}}:8088/update/latest.json
api_uri: http://{{server}}:8000
ws_uri: ws://{{server}}:8888

위에 있는 server 가 변수 역할을 하고,
하단에 {{server}} 부분에 다 치환되기를 말이지요.

결국 이를 위해서 jinja 모듈의 템플릿을 같이 사용하여
해결해 보았습니다.

우선 설치할 모듈은 다음 두 개 입니다.

PyYAML
jinja2

그리고, 코드는 다음과 같습니다.

################################################################################
import yaml
from jinja2 import Template, Undefined
from pprint import pprint


################################################################################
class NullUndefined(Undefined):
    def __getattr__(self, key):
        return ''


################################################################################
def get_yaml_conf(f):
    with open(f, encoding='utf-8') as ifp:
        def_conf = yaml.load(ifp)
        return def_conf


################################################################################
def get_jinja_yaml_conf(f):
    with open(f, encoding='utf-8') as ifp:
        # def_conf = yaml.load(ifp)
        t = Template(ifp.read(), undefined=NullUndefined)
        c = yaml.safe_load(t.render())
        def_conf = yaml.safe_load(t.render(c))
        return def_conf


################################################################################
if __name__ == '__main__':
    f = 'test-config.yaml'
    conf = get_yaml_conf(f)
    pprint(conf)
    conf = get_jinja_yaml_conf(f)
    pprint(conf)


첫번째 기존의 단순 yaml을 로드한 경우에는

{'api_uri': 'http://{{server}}:8000',
 'check_agent_sec': 10,
 'check_agent_update_json': 'http://{{server}}:8088/update/latest.json',
 'check_agent_update_sec': 3600,
 'server': '10.211.55.29',
 'ws_uri': 'ws://{{server}}:8888'}

와 같이 보이지만,

이제 치환된 결과는

{'api_uri': 'http://10.211.55.29:8000',
 'check_agent_sec': 10,
 'check_agent_update_json': 'http://10.211.55.29:8088/update/latest.json',
 'check_agent_update_sec': 3600,
 'server': '10.211.55.29',
 'ws_uri': 'ws://10.211.55.29:8888'}

와 같이 원하는 결과가 나옵니다.


어느 분께는 도움이 되셨기를 ..

덧글

  • ㅇㅇ 2020/12/05 07:49 # 삭제 답글

    pip로 OmegaConf 설치하시면 바로 됩니다.

    https://omegaconf.readthedocs.io/en/2.0_branch/usage.html#variable-interpolation

    server:
    host: localhost
    port: 80

    client:
    url: http://${server.host}:${server.port}/
    server_port: ${server.port}
  • 지훈현서아빠 2020/12/06 13:01 #

    아.. 네. 이것으로 하는 것도 방법이네요.
    고맙습니다.
댓글 입력 영역

구글애드텍스트