[Python] PyYAML 사용 시 키 이름 "on"이 True로 바뀌는 사례

PyYAML 사용 시 키 이름 “on”이 True로 바뀌는 사례


환경

  • Github Actions
  • Python
  • PyYAML


배경

  • Github Actions Workflow 파일을 동적으로 Python을 통해 수정하는데 YAML 파일 파싱시 on이라는 키가 True로 바뀌는 상황이 발생해서 정리.


예시

아래와 같이 Python에서 yaml을 통해 파일을 읽어서 출력하면 on이 사라지고 True가 들어가 있는걸 볼 수 있다.

코드

import io
import yaml

file_content = """
name: Workflow Complete Event Test

on:
  workflow_run:
    workflows: [ "Push Main Branch" ]
    types:
      - completed
"""

file_like_object = io.StringIO(file_content)
yaml_content = yaml.safe_load(file_like_object)

print(yaml_content)

결과

{'name': 'Workflow Complete Event Test', True: {'workflow_run': {'workflows': ['Push Main Branch'], 'types': ['completed']}}}


이유

검색해보니 PyYAML의 경우 YAML 1.1 버전을 지원하고 있으며 1.1 버전의경우 "on"은 boolean으로 간주되며 그렇기에 True로 바뀌는게 맞다고 한다. YAML 1.2를 아직 지원하지 않다고 하기에 의도된 동작이며 방법을 따로 찾아야한다.


해결 방법

여러가지 방식이 있다.

  • Loader의 코드를 변경해서 설정
  • Key에 따옴표("" 또는 '')를 사용
  • 다른 Python 모듈 사용

따옴표가 눈에 띄어서 없애고 싶은 마음이 들지만 두번째 방식이 가장 간단해보이고 기존 yaml 모듈 변경이 없어서 해당 방식을 적용했다.

코드

import io
import yaml

file_content = """
name: Workflow Complete Event Test

'on':
  workflow_run:
    workflows: [ "Push Main Branch" ]
    types:
      - completed
"""

file_like_object = io.StringIO(file_content)
yaml_content = yaml.safe_load(file_like_object)

print(yaml_content)

결과

{'name': 'Workflow Complete Event Test', 'on': {'workflow_run': {'workflows': ['Push Main Branch'], 'types': ['completed']}}}


기타

True를 키 이름으로 사용

  • 키가 True로 잡히는데 Python에서 True를 사용하니 접근이 가능했다.

코드

import io
import yaml

file_content = """
name: Workflow Complete Event Test

on:
  workflow_run:
    workflows: [ "Push Main Branch" ]
    types:
      - completed
key:
  on: "test"
"""

file_like_object = io.StringIO(file_content)
yaml_content = yaml.safe_load(file_like_object)

print(yaml_content[True])

결과

{'workflow_run': {'workflows': ['Push Main Branch'], 'types': ['completed']}}


YAML 파일 생성 시 생성되는 키 이름

  • 여기서 yaml.dump를 통해 파일을 만들면 키는 true로 들어간다.

코드

import io
import yaml

file_content = """
name: Workflow Complete Event Test

on:
  workflow_run:
    workflows: [ "Push Main Branch" ]
    types:
      - completed
key:
  on: "test"
"""

file_like_object = io.StringIO(file_content)
yaml_content = yaml.safe_load(file_like_object)

with open('example.yaml', 'w') as file:
    yaml.dump(yaml_content, file)

결과

$ cat example.yaml
name: Workflow Complete Event Test
true:
  workflow_run:
    types:
    - completed
    workflows:
    - Push Main Branch
key:
  true: test


참고자료