使用Pyyaml或Ruamel.yaml

问题描述

我有一个.yaml文件,其结构如下:

%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

到目前为止,我一直在使用PyYaml库打开文件,并使用以下代码片段将每个参数和值保存到代码中的数组中:

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

一个代码段跳过了第一行,因为该程序由于文件的第一行而中断:%Yaml:1.0

当我尝试编辑读取的行之一以更改值,然后将其保存回配置文件时,就会出现问题。我已经尝试了pyyaml和ruamel.yaml示例,但是它们要么更改了文件的整个方面(删除了我特别不在意的注释,要么根本不更改了值)。

我还发现,当我尝试转储新更改的值时,%yaml:1.0没有传递到已编辑的文件上,这导致使用该文件的软件崩溃。有没有一种方法可以编辑YAML文件中的值,以便可以对其进行更改,但是结构(标题和可能的注释)不受此影响?

如果没有,该如何做,以便可以编辑YAML文件以使其完全保留原样,但其值已更改?

解决方法

您将必须更新/更改yaml_loader返回的数据结构,然后 重新添加YAML 1.0标头:

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()

给出:

%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