Syntax of multiple dictionaries in one YAML file and how to access each one of them with PyYAML

120

Question: Syntax of multiple dictionaries in one YAML file and how to access each one of them with PyYAML

I have a few small dictionaries which I would like to include in one yaml file and access each one of them separately with PyYAML. After having some trouble finding out how to write the YAML file, I ended up with this version, where --- is supposed to distinguish the two dictionaries, which are named as elements and as parameters. This was inspired by this post and answer

--- !elements n: 'N' p: 'P' k: 'K' --- !parameters ph: 'pH' org_mat : 'organic matter' 

To continue, I created a variable with the name of the path of the file: yaml_fpath = r"\Users\user1\Desktop\yaml_file" and I tried several methods to access the dictionaries, such as:

for item in  yaml.safe_load_all(yaml_fpath):     print(item) 

or

yaml.safe_load(open(yaml_fpath, 'r', encoding = 'utf-8')) 

but none does what I need. In fact, I would like to load the file and be able to call each dictionary python error by each name when I need to use it.

What am I missing from the documentation of PyYAML?

Total Answers: 1

53

Answers 1: of Syntax of multiple dictionaries in one YAML file and how to access each one of them with PyYAML

Assume you have multiple YAML files in a directory that consist python error of a root level mapping that is tagged:

!elements n: 'N' p: 'P' k: 'K' 

If these files have the recommended suffix for YAML files you can combine them using:

import sys import ruamel.yaml  from pathlib import Path  file_out = Path('out.yaml')  yaml = ruamel.yaml.YAML() yaml.preserve_quotes = True yaml.explicit_start = True   data = [] for file_name in Path('.').glob('*.yaml'):     if file_name.name == file_out.name:         continue     print('appending', file_name)     data.append(yaml.load(file_name))  yaml.dump_all(data, file_out) print(file_out.read_text()) 

which gives:

appending file1.yaml appending file2.yaml --- !elements n: 'N' p: 'P' k: 'K' --- !parameters ph: 'pH' org_mat: 'organic matter' 

There is no need to register any classes that can handle the tag if you use the (default) roundtrip mode. You do have to set explicit_start to get the leading directives end indicator (---, often incorrectly called document separator, although it doesn't have to appear at the beginning of a document). The other directives end indicators are a result of using dump_all() instead of dump().

If you want to access some value, assuming you don't know where it is in out.yaml, but knowing the tag and key, you can do:

import sys import ruamel.yaml  from pathlib import Path  file_in = Path('out.yaml')  yaml = ruamel.yaml.YAML() yaml.preserve_quotes = True data = yaml.load_all(file_in)  my_tag = 'parameters' my_key = 'org_mat'  for d in data:     if d.tag.value == '!' + my_tag:         if my_key in d:             print('found ->', d[my_key]) 

which gives:

found -> organic matter