简体   繁体   中英

Editing a .yaml file in Python using Pyyaml or Ruamel.yaml

I have a .yaml file with the following structure:

%YAML:1.0
#--------------------------------------------------------------------------------------------
# Camera Parameters. Adjust them!
#--------------------------------------------------------------------------------------------

#Camera calibration and distortion parameters (OpenCV)

Camera.fx: 707.0912
Camera.fy: 707.0912
Camera.cx: 601.8873
Camera.cy: 183.1104

So far, I have been using the PyYaml library to open the file and save each of the parameters and values into arrays in my code with the following snippet:

def configFileManipulator():
    path = filedir+"KITTI04-12.yaml"
    data = yaml_loader(path)
    config = data.items()

    #print(data)
    for item, value in config:
        parameter_list.append(item)
        parameter_values.append(value)

def yaml_loader(filepath):
    """Loads a yaml file """
    with open(filepath, "r") as file:
        _ = file.readline()
        doc = yaml.load(file, Loader=yaml.FullLoader)
    return doc

The previous snippet skips the first line because the program was breaking down due to the file's first line: %Yaml:1.0 .

The problem comes when I try to edit one of the lines read to change the value and then save it back to the configuration file. I have tried both pyyaml and ruamel.yaml examples, but they either change the whole aspect of the file (erasing the comments, which I particularly don't mind, or not changing the value at all).

I have also found out that when I try to dump the newly changed values, the %yaml:1.0 is not passed onto the edited file, which causes the software that uses that file to crash. Is there a way to edit the values within the YAML file, so that they can be changed, but the structure (the header and possibly the comments) are not afflicted by this?

If there is not, how do I make it so that I can edit the YAML file to leave it exactly as it is but with a changed value?

You'll have to update/change the data structure that is returned by yaml_loader, and then re-add the YAML 1.0 header:

import ruamel.yaml
import sys

filedir = ""

def yaml_loader(file_path):
    yaml = ruamel.yaml.YAML()
    with open(file_path, 'rb') as fp:
        _ = fp.readline()
        return yaml.load(fp)

def yaml_dumper(data, file_path=None):
    def yaml_to_stream(data, s):
        yaml = ruamel.yaml.YAML()
        s.write('%YAML:1.0\n')
        yaml.dump(data, s)

    if file_path is None:
        yaml_to_stream(data, sys.stdout)
    else:
        with open(file_path, 'wb') as fp:
            yaml_to_stream(data, fp)


def config_file_manipulator():
    path = filedir+"KITTI04-12.yaml"
    data = yaml_loader(path)
    config = data.items()

    data['Camera.cx'] = 192.54     # update a value
    del data['Camera.cy']          # delete a value
    data['Camera.cz'] = 42.42      # add a value

    yaml_dumper(data) # or yaml_dumper(data, path) to rewrite the file

config_file_manipulator()

which gives:

%YAML:1.0
#--------------------------------------------------------------------------------------------
# Camera Parameters. Adjust them!
#--------------------------------------------------------------------------------------------

#Camera calibration and distortion parameters (OpenCV)

Camera.fx: 707.0912
Camera.fy: 707.0912
Camera.cx: 192.54
Camera.cz: 42.42

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM