1

I have a YAML file with content:

---
  'Croatia':
    population: 4600000
    capital: Zagreb
  'Italy':
    population: 60000000
    capital: Rome

How do I want to add a new field:

---
  'Croatia':
    population: 4600000
    capital: Zagreb
    continent: Europe
  'Italy':
    population: 60000000
    capital: Rome
    continent: Europe

How do I add the field "continent" with value Europe to every State?

David
  • 1,469
  • 5
  • 33
  • 51
  • What have you tried so far? – Klaus D. Apr 11 '18 at 03:53
  • Possible duplicate of [Editing Yaml File by Python](https://stackoverflow.com/questions/29518833/editing-yaml-file-by-python) – viraptor Apr 11 '18 at 03:56
  • Your second example missed a colon after `'Croatia'`, making it invalid YAML. There is also no mention of fields in the YAML specification. A mapping has keys and values. – Anthon Apr 11 '18 at 06:04

2 Answers2

0

Load it, update the field as usual in a dictionary and dump again.

data = yaml.load(...)
data['Croatia']['continent'] = 'Europe'
yaml.dump(data, ...)
viraptor
  • 33,322
  • 10
  • 107
  • 191
  • 1
    There is absolutely no reason to use the unsafe `load()` instead of `safe_load()`. You should also indicate that doing this drops the (superfluous) quotes around `'Croatia'`, doesn't have the indentation that the OP requested, nor does it have the start of document marker. – Anthon Apr 11 '18 at 06:13
0

If you want to preserve your original YAML layout and quoting, then you cannot generally do that with pyyaml without a lot of effort.

With ruamel.yaml (disclaimer: I am the author of that package) this is much simpler, but you still need to do something for the top-level indentation by two spaces (using the transform parameter):

import sys
import ruamel.yaml

yaml_str = """\
---
  'Croatia':
    population: 4600000
    capital: Zagreb
"""

def indent_data(s):
    return s.replace('\n', '\n  ')

yaml = ruamel.yaml.YAML()
# yaml.indent(mapping=4, sequence=4, offset=2)
yaml.preserve_quotes = True
yaml.explicit_start = True
data = yaml.load(yaml_str)
data['Croatia']['continent'] = 'Europe'
yaml.dump(data, sys.stdout, transform=indent_data)

gives:

---
  'Croatia':
    population: 4600000
    capital: Zagreb
    continent: Europe

Any comments in the original document would be preserved in the output, but EOL comments might shift because of the extra indentation.

Anthon
  • 69,918
  • 32
  • 186
  • 246
  • @Becks Yes you can, by passing the result of `open(your_file_name.yaml)` instead of `yaml_str` to `yaml.load()`. Using the `yaml_str` in just to have a single source testable example. – Anthon Apr 17 '18 at 05:08