Parsing yaml file with --- in python

Viewed 2344

How can we parse a file which contains multiple configs and which are separated by --- in python.
I've config file which looks like

File name temp.yaml

%YAML 1.2
---
name: first
cmp:
- Some: first
  top:
    top_rate: 16000
    audio_device: "pulse"

---
name: second
components:
- name: second
  parameters:
    always_on: true
    timeout: 200000

When I read it with

import yaml
with open('./temp.yaml', 'r') as f:
    temp = yaml.load(f)

I am getting following error

 temp = yaml.load(f)
Traceback (most recent call last):
  File "temp.py", line 4, in <module>
    temp = yaml.load(f)
  File "/home/pranjald/.local/lib/python3.6/site-packages/yaml/__init__.py", line 114, in load
    return loader.get_single_data()
  File "/home/pranjald/.local/lib/python3.6/site-packages/yaml/constructor.py", line 41, in get_single_data
    node = self.get_single_node()
  File "/home/pranjald/.local/lib/python3.6/site-packages/yaml/composer.py", line 43, in get_single_node
    event.start_mark)
yaml.composer.ComposerError: expected a single document in the stream
  in "./temp.yaml", line 3, column 1
but found another document
  in "./temp.yaml", line 10, column 1

1 Answers

Your input is composed of multiple YAML documents. For that you will need yaml.load_all() or better yet yaml.safe_load_all(). (The latter will not construct arbitrary Python objects outside of data-like structures such as list/dict.)

import yaml

with open('temp.yaml') as f:
    temp = yaml.safe_load_all(f)

As hinted at by the error message, yaml.load() is strict about accepting only a single YAML document.

Note that safe_load_all() returns a generator of Python objects which you'll need to iterate over.

>>> gen = yaml.safe_load_all(f)
>>> next(gen)
{'name': 'first', 'cmp': [{'Some': 'first', 'top': {'top_rate': 16000, 'audio_device': 'pulse'}}]}
>>> next(gen)
{'name': 'second', 'components': [{'name': 'second', 'parameters': {'always_on': True, 'timeout': 200000}}]}
Related