Editing YAML file by Python
Asked Answered
P

3

29

I have a YAML file that looks like this:

# Sense 1
- name  : sense1
  type  : float
  value : 31

# sense 2
- name  : sense2
  type  : uint32_t
  value : 1488

# Sense 3
- name  : sense3
  type  : int32_t
  value : 0

- name  : sense4
  type  : int32_t
  value : 0
- name  : sense5
  type  : int32_t
  value : 0
- name  : sense6
  type  : int32_t
  value : 0

I want to use Python to open this file, change some of the values (see above) and close the file. How can I do that ?

For instance I want to set sense2[value]=1234, keeping the YAML output the same.

Pyrethrin answered 8/4, 2015 at 15:23 Comment(1)
Check PyYAML: pyyaml.org/wiki/PyYAMLJazmin
T
42

If you care about preserving the order of your mapping keys, the comment and the white space between the elements of the root-level sequence, e.g. because this file is under revision control, then you should use ruamel.yaml (disclaimer: I am the author of that package).

Assuming your YAML document is in the file input.yaml:

import sys
import ruamel.yaml

yaml = ruamel.yaml.YAML()
# yaml.preserve_quotes = True
with open('input.yaml') as fp:
    data = yaml.load(fp)
for elem in data:
    if elem['name'] == 'sense2':
         elem['value'] = 1234
         break  # no need to iterate further
yaml.dump(data, sys.stdout)

gives:

# Sense 1
- name: sense1
  type: float
  value: 31

# sense 2
- name: sense2
  type: uint32_t
  value: 1234

# Sense 3
- name: sense3
  type: int32_t
  value: 0

- name: sense4
  type: int32_t
  value: 0
- name: sense5
  type: int32_t
  value: 0
- name: sense6
  type: int32_t
  value: 0

This can safely be used on untrusted YAML. The (default) RoundtripLoader is a subclass of the SafeLoader even though it can handle and preserve tags (which it doesn't interpret in the dangerous way PyYAML does when enabling loading of unregistered tags).

Thunderstruck answered 11/4, 2018 at 6:26 Comment(4)
and ruamel.yaml.YAML(typ='safe') for untrusted inputBacchanal
@PatMyron I am not sure what you are tyring to say here. The default ruamel.yaml.YAML() equals ruamel.yaml.YAML(typ='rt') gets you a subclass of the SafeLoader that can deal with tags (but not in the way the untrusted Loader does) which can safely be used on untrusted sources, without losing comments/tags etc.Thunderstruck
unfortunately my ymal is totally changed and the comments are disappeared though i only wanted to change one simple line of versionTwocycle
@Twocycle ruamel.yaml doesn't support the ymal format.Thunderstruck
P
34
import yaml

with open("data.yaml") as f:
     list_doc = yaml.safe_load(f)

for sense in list_doc:
    if sense["name"] == "sense2":
         sense["value"] = 1234

with open("data.yaml", "w") as f:
    yaml.dump(list_doc, f)
Phenylalanine answered 8/4, 2015 at 15:40 Comment(6)
Thanks jwilner - It's actually change the format of the Yaml (not wanted !) e.g.- got {name: sense_base_temp, type: float, value: 31} - {name: sense_common_delay, type: uint32_t, value: 1488} - {name: sense1, type: int32_t, value: 0} - {name: sense2, type: int32_t, value: 0} - {name: sense3, type: int32_t, value: 0} - {name: sense4, type: int32_t, value: 0}Pyrethrin
Ah, I get what you want. I think you want to call yaml.dump with the keyword argument default_flow_style=FalsePhenylalanine
Yep - now it is fine !! - but all comments in the original Yaml where gone... (:<) - is there a way to read - modify- save (like a any text file) without change any other issue?Pyrethrin
Doesn't look like you can preserve comments: #7256385. If your changes are simple, you could just read the file as a string and use string manipulation.Phenylalanine
There is almost never a need to use the unsafe load(), certainly not here. You should always use safe_load() instead. sense_2 is nowhere in the OPs input, so I assumed that to be a typo. You can certainly preserve comments, see the most upvoted answer to the question you link to (posted long before this answer).Thunderstruck
As of version 5.1, you should use yaml.load(<path>, Loader=yaml.FullLoader) to avoid warnings.Purplish
I
0

This script allows you to update specific fields in a YAML file by providing field-value pairs as command-line arguments.

https://github.com/ataha/python-snippets/blob/master/YAML_modifier/YAML_Modifier.py

Insulate answered 8/7, 2023 at 18:31 Comment(1)
While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - From ReviewGreggs

© 2022 - 2024 — McMap. All rights reserved.