If you read through the PyYAML documentation, you will see that it
tells you that using the load()
function is potentially dangerous,
so the first thing to do (since you, and almost everybody else don't
need it), is not using that, but using safe_load()
instead.
You should also change your input file to config.yaml
, the
recommended extension for YAML files has been .yaml
since at 2006.
Knowing that, the way to change a config.yaml
file using PyYAML:
import yaml
with open('config.yaml') as stream:
data = yaml.safe_load(stream)
test = data['test']
test.update(dict(name="Tom", age="10", version="2.2"))
with open('output.yaml', 'wb') as stream:
yaml.safe_dump(data, stream, default_flow_style=False,
explicit_start=True, allow_unicode=True, encoding='utf-8')
This will get you an output.yaml
that looks like:
---
test:
age: '10'
name: Tom
version: '2.2'
The default_flow_style
parameter is necessary to not get a JSON like
structure for your leaf node mapping. The explicit_start
to get the
leading diretives end indicator (---
), and I recommend to always use
allow_unicode=True, encoding='utf-8'
(and open the file as binary)
in order not to run into surprises or problems when you change name
to Björk Guðmundsdóttir
.
Now as you will notice, this doesn't generate the output that you want
(although semantically the same):
- single quotes instead of double quotes around the strings that could be interpreted as numbers
- no double quotes around
Tom
- sorting of the keys of your mapping
If you had any comments in the YAML file, these would have been lost.
The better way to update YAML files is using ruamel.yaml
(disclaimer: I am the author of that package), which has some more
sany defaults than PyYAML, handles YAML 1.2 and doesn't drop comments
(if you would have them in your file):
import ruamel.yaml
yaml = ruamel.yaml.YAML()
yaml.preserve_quotes = True
yaml.explicit_start = True
with open('config.yaml') as stream:
data = yaml.load(stream)
test = data['test']
test.update(dict(name="Tom", age="10", version="2.2"))
with open('output.yaml', 'wb') as stream:
yaml.dump(data, stream)
with that your output file will be:
---
test:
name: "Tom"
age: "10"
version: "2.2"
which is exactly what you wanted.