'Python 으로 YAML 파싱해서 읽기'에 해당되는 글 1건

  1. 2020.06.28 [Python] PyYAML로 YAML 파일 읽고 쓰기 (Parse and Serialize YAML in Python) 6

이전 포스팅에서 Python으로 JSON 데이터 읽고 쓰기, XML 데이터 읽고 쓰기에 대해서 소개한 적이 있습니다.  이번 포스팅에서는 Python의 PyYAML 라이브러리를 이용하여 YAML 파일을 파싱하여 파이썬 객체로 읽어오기, Python 객체를 YAML 파일로 쓰는 방법을 소개하겠습니다. 



YAML에 대한 Wikipedia의 소개를 먼저 살펴보겠습니다. 

YAML 은 "YAML Ain't Markup Language" 의 반복적인 약어(recursive acronym)로서, 인간이 읽을 수 있는 데이터 직렬화 언어(human-readable data-serialization language) 입니다. YAML 은 데이터가 저장되거나 전송되는 구성 파일(configuration file)과 애플리케이션에서 종종 사용됩니다. YAML은 XML 과 동일한 커뮤니케이션 애플리케이션을 대상으로 하지만 최소한의 구문을 가지고 있습니다. 

* source: https://en.wikipedia.org/wiki/YAML


아래는 데이터가 저장되거나 전송되는 구성파일을 XML과 JSON, YAML으로 나타내서 비교한 예입니다. Python 들여쓰기(indentation) 형태로 해서 XML 이나 JSON 대비 Syntax 가 매우 간소해졌음을 알 수 있습니다. 




Python 에서 YAML 파일을 파싱하거나, 반대로 Python 객체를 YAML 파일로 내보낼 때는 PyYAML 라이브러리 (PyYAML is YAML parser and emitter for python)를 사용합니다. 이전에 XML이나 JSON을 다루었을 때와 PyYAML 라이브러리의 load(), dump() 함수 사용법은 비슷합니다. 





먼저, PyYAML 라이브러리가 설치되어 있지 않다면 명령 프롬프트에서 pip로 설치를 해주면 됩니다. 




  (1) YAML 파일을 파싱해서 Python 객체로 읽어오기: yaml.load()


예제로 사용한 YAML 파일은 아래처럼 'Vegetables' 키에 'Pepper', 'Tamato', 'Garlic' 을 값으로 가지는 YAML 파일(vegetables.yml)입니다. (Notepad++ 에디터에서 파일 형식을 YAML로 해서 작성하면 들여쓰기를 알아서 맞추어 줍니다. PyCharm 같은 프로그래밍 에디터를 사용해도 편리합니다.)



vegetables.yml


with open() 으로 'vegetables.yml' YAML 파일을 연 후에, yaml.load() 함수로 YAML 파일을 파싱하여 vegetables 라는 이름의 Python 객체로 저장하였습니다. Python 객체를 인쇄해보면 Key, Value (list) 로 구성된 Dictionary 로 YAML 파일을 파싱했음을 알 수 있습니다. 



import yaml


with open('vegetables.yml') as f:

    vegetables = yaml.load(f, Loader=yaml.FullLoader)

    print(vegetables)

 

{'Vegetables': ['Pepper', 'Tomato', 'Garlic']}




아래와 같이 Kubernetes의 deployment-definition.yaml 처럼 조금 복잡한 YAML 파일을 PyYAML 로 파싱해보면 List와 Nested Dictionary 로 구성된 Dictionary로 파싱합니다. 



k8s_deployment_yaml.yml




import yaml


with open('deployment-definition.yml') as f:

    deployment_def = yaml.load(f, Loader=yaml.FullLoader)


deployment_def

{'apiVersion': 'apps/v1',
 'kind': 'Deployment',
 'metadata': {'name': 'frontend',
  'labels': {'app': 'mywebsite', 'tier': 'frontend'}},
 'spec': {'replicas': 3,
  'template': {'metadata': {'name': 'myapp-pod', 'labels': {'app': 'myapp'}},
   'spec': {'containers': [{'name': 'nginx', 'image': 'nginx'}]}},
  'selector': {'matchLabels': {'app': 'myapp'}}}}





  (2) 여러개의 YAML 문서들을 파싱하여 읽어오기 : yaml.load_all()


YAML 문서를 구분할 때는 '---' 를 사용합니다. 아래는 'Fruits'와 'Vegetables' 의 두개의 YAML 문서를 '---'로 구분해서 하나의 YAML 파일로 만든 것입니다. 



예제 파일:

fruit-vegetable.yml



위의 (1)번에서는 1개의 YAML 문서를 yaml.load() 함수로 Python으로 읽어왔었다면, 이번의 (2)번에서는 '---'로 구분되어 있는 여러개의 YAML 문서를 yaml.load_all() 함수를 사용해서 Python 객체로 파싱하여 읽어오겠습니다. 



import yaml


with open('fruit-vegetable.yml') as f:

    

    fruits_vegetables = yaml.load_all(f, Loader=yaml.FullLoader)

    

    for fruit_vegetable in fruits_vegetables:

        print(fruit_vegetable)

 

{'Fruits': ['Blueberry', 'Apple', 'Orange']}
{'Vegetables': ['Pepper', 'Tomato', 'Garlic']}




  (3) 읽어온 YAML 파일을 정렬하기


아래와 같이 자동차 브랜드, 가격 쌍으로 이우러진 cars.yml YAML 파일을 Python 객체로 파싱해서 읽어올 때 Key 기준, Value 기준으로 각각 정렬을 해보겠습니다. (Dictionary 정렬 방법 사용)



cars.yml


(3-1) 읽어온 YAML 파일을 Key 기준으로 정렬하기 (sorting by Key)

    : 방법 1) yaml.dump(object, sort_keys=True) 



import yaml


with open('cars.yml') as f:

    

    cars_original = yaml.load(f, Loader=yaml.FullLoader)

    print(cars_original)

    

    print("---------------------")

    

    # sorting by Key

    cars_sorted = yaml.dump(cars_original, sort_keys=True)

    print(cars_sorted)

 

{'hyundai': 45000, 'tesla': 65000, 'chevrolet': 42000, 'audi': 51000, 'mercedesbenz': 80000}
---------------------
audi: 51000
chevrolet: 42000
hyundai: 45000
mercedesbenz: 80000
tesla: 65000



  : 방법 2) sorted(object.items()) 메소드 사용 



import yaml


with open('cars.yml') as f:

    

    cars_original = yaml.load(f, Loader=yaml.FullLoader)

    print(cars_original)

    

    print("---------------------")

    # sort by key in ascending order

    for key, value in sorted(cars_original.items()):

        print(key, ':', value


{'hyundai': 45000, 'tesla': 65000, 'chevrolet': 42000, 'audi': 51000, 'mercedesbenz': 80000}
---------------------
audi : 51000
chevrolet : 42000
hyundai : 45000
mercedesbenz : 80000
tesla : 65000

 



(3-2) Key 값의 역순으로 정렬 (sorting in reverse order): sorted(object.items(), reverse=True)



import yaml


with open('cars.yml') as f:

    cars_original = yaml.load(f, Loader=yaml.FullLoader)

    print(cars_original)

    

    print("---------------------")

    

    # sorting by key in reverse order

    for key, value in sorted(cars_original.items(), reverse=True):

        print(key, ':', value)


tesla : 65000
mercedesbenz : 80000
hyundai : 45000
chevrolet : 42000
audi : 51000




(3-3) 읽어온 YAML 파일을 Value 기준으로 정렬하기 (sorting by Value)



import yaml


with open('cars.yml') as f:

    cars_original = yaml.load(f, Loader=yaml.FullLoader)

    print(cars_original)

    

    print("---------------------")

    # sorting by value in ascending order

    for key, value in sorted(cars_original.items(), key = lambda item: item[1]):

        print(key, ':', value)


{'hyundai': 45000, 'tesla': 65000, 'chevrolet': 42000, 'audi': 51000, 'mercedesbenz': 80000}
---------------------
chevrolet : 42000
hyundai : 45000
audi : 51000
tesla : 65000
mercedesbenz : 80000




  (4) Python 객체를 YAML stream으로 직렬화 하기: yaml.dump()


Key, Value 쌍으로 이루어진 Python Dictionary를 yaml.dump() 메소드를 사용해서 YAML stream으로 직렬화해보겠습니다. 



import yaml


fruits = {'fruits': ['blueberry', 'apple', 'orange']}


# serialize a Python object into YAML stream

fruits_serialized_yaml = yaml.dump(fruits)

print(fruits_serialized_yaml)

 

fruits:
- blueberry
- apple
- orange




  (5) Python 객체를 YAML 파일로 쓰기: with open('w') as f: yaml.dump()


위의 (4)번에서 소개한, YAML stream으로 직렬화하는 yaml.dump() 메소드에 with open('w') 함수를 같이 사용해서 이번에는 YAML file 에 쓰기('w')를 해보겠습니다. 



import yaml


fruits = {'fruits': ['blueberry', 'apple', 'orange']}


with open('fruits.yaml', 'w') as f:

    yaml.dump(fruits, f)




많은 도움이 되었기를 바랍니다. 

이번 포스팅이 도움이 되었다면 아래의 '공감~'를 꾹 눌러주세요. 



728x90
반응형
Posted by Rfriend
,