Reputation: 7784
Im inserting a key into Yaml using python but I would like to preserve order and comments in the yaml
#This Key is used for identifying Parent tests
ParentTest:
test:
JOb1: myjob
name: testjob
arrive: yes
Now Im using below code to insert new key
params['ParentTest']['test']['new_key']='new value'
yaml_output=yaml.dump(pipeline_params, default_flow_style=False)
How to preserve the exact order and comments ?
Below arrive moved up but I want to preserve order & comments as well
output is :
ParentTest:
test:
arrive: yes
JOb1: myjob
name: testjob
Upvotes: 13
Views: 9827
Reputation: 4346
pyyaml cannot keep comments, but ruamel does.
Try this:
doc = ruamel.yaml.load(yaml, Loader=ruamel.yaml.RoundTripLoader)
doc['ParentTest']['test']['new_key'] = 'new value'
print ruamel.yaml.dump(doc, Dumper=ruamel.yaml.RoundTripDumper)
The order of keys will also be preserved.
Edit: Look at Anthon's answer from 2020: https://stackoverflow.com/a/59659659/93745
Upvotes: 10
Reputation: 167
Addtion,if you want keep quote,you can try this:
import ruamel.yaml
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
Upvotes: 1
Reputation: 76802
Although @tinita's answer works, it uses the old ruamel.yaml API and
that gives you less control over the loading/dumping. Even so, you
cannot preserve the inconsistent indentation of your mappings: the key
ParentTest
is indented four positions, the key test
a further
three and the key JOb1
only two positions. You can "only" set the
same indentation for all mappings (i.e their keys), and separate from
that the indentation of all sequences (i.e. their elements) and if
there is enough space, you can offset the sequence indicator (-
) within
the sequence element indent.
In the default, round-trip mode, ruamel.yaml preserves key order, and additionally you can preserve quotes, folded and literal scalars.
With a slightly extended YAML input as example:
import sys
import ruamel.yaml
yaml_str = """\
#This Key is used for identifying Parent tests
ParentTest:
test:
JOb1:
- my
- job
# ^ four indent positions for the sequence elements
# ^ two position offset for the sequence indicator '-'
name: 'testjob' # quotes added to show working of .preserve_quotes = True
arrive: yes
"""
yaml = ruamel.yaml.YAML()
yaml.indent(mapping=4, sequence=4, offset=2)
yaml.preserve_quotes = True
params = yaml.load(yaml_str)
params['ParentTest']['test']['new_key'] = 'new value'
params['ParentTest']['test'].yaml_add_eol_comment('some comment', key='new_key', column=40) # column is optional
yaml.dump(params, sys.stdout)
which gives:
#This Key is used for identifying Parent tests
ParentTest:
test:
JOb1:
- my
- job
# ^ four indent positions for the sequence elements
# ^ two position offset for the sequence indicator '-'
name: 'testjob' # quotes added to show working of .preserve_quotes = True
arrive: yes
new_key: new value # some comment
Upvotes: 8