[configuration file] yaml configuration file read / write resolution [python and C + +]

Content of this article:

This section mainly introduces how to read, write and parse the configuration file yaml.                 

Basic introduction:

In daily development, we can always encounter some scenarios that may need to be changed. At this time, we need a configuration file to change the running parameters of the program without changing the program.

There are many common configuration file formats, including json, protobuf, xml, and yaml format. Of course, the reason for choosing yaml is that it is simpler and more powerful than xml, json and other languages.

YAML is "YAML Ain't a Markup Language" Markup Language )Yes Recursive acronym . In fact, YAML actually means "Yet Another Markup Language" Markup Language )However, in order to emphasize that the language is data centric rather than focusing on markup language, it is renamed with reverse abbreviations.         

Basic syntax:

1. Case sensitive;

2. Use indentation to indicate hierarchical relationship;

3. Only spaces are allowed, not tab s;

4. The same level only needs to indent the same space;

5. Use # notes

python practices:

First, simply write a configuration file for the camera class to be tested, which is as follows:

#Global configuration parameters
GlobalConfig:
 DeviceNum: 3

#Equipment configuration parameters
# '-' are different items in the array
DeviceParam:
 - ID: 1
   DeviceName: Dev_1
   DeviceIp: 192.168.2.111
   FrameRate: 24
   DepthType: 3
   FrameWidth: 1200
   FrameHeight: 1024
   TriggerInterval: 300

 - ID: 2
   DeviceName: Dev_2
   DeviceIp: 192.168.2.112
   FrameRate: 24
   DepthType: 3
   FrameWidth: 1200
   FrameHeight: 1024
   TriggerInterval: 300

 - ID: 3
   DeviceName: Dev_3
   DeviceIp: 192.168.2.113
   FrameRate: 24
   DepthType: 3
   FrameWidth: 1200
   FrameHeight: 1024
   TriggerInterval: 300

The resolver is as follows:

Note: Loader = yaml shall be added Fullloader, otherwise a warning will be issued.

# coding=utf-8
import yaml

with open("./config.yaml") as f:
	x = yaml.load(f,Loader= yaml.FullLoader)

# print(x)
#Print out the number of all devices in the global configuration parameters
print("parse device count is ",x["GlobalConfig"]['DeviceNum'])
#Print out the contents of device 1 in the device configuration parameters
print("parse device1 param is ",x["DeviceParam"]["Device1"])

The output results are as follows

parse device count is  3
parse device1 param is  {'TriggerInterval': 300, 'DepthType': 3, 'ID': 1, 'DeviceName': 'Dev_1', 'DeviceFrameRate': 24, 'SourceHeight': 1024, 'DeviceIp': '192.168.2.111', 'SourceWidth': 1200}

Format write yaml file:

#Write the fixed format string assembly to wryaml Yaml file
data = {"GlobalConfig":{'ConfigName':'CameraManagerConfig','DeviceNum':3},'DeviceParam':{'Device1':{'DeviceName':'Dev_1','DeviceIp':'192.168.1.100','DeviceType':3}}}
with open("./wrYaml.yaml",'w') as f:
	yaml.dump(data,f)

#Read parse wryaml Yaml file content
with open("./wrYaml.yaml") as f:
	x = yaml.load(f,Loader= yaml.FullLoader)

print(x['GlobalConfig']['DeviceNum'])
print(x['DeviceParam']['Device1'])

Write results after execution:

DeviceParam:
  Device1:
    DeviceIp: 192.168.1.100
    DeviceName: Dev_1
    DeviceType: 3
GlobalConfig:
  ConfigName: CameraManagerConfig
  DeviceNum: 3

C + + practice:

The configuration file of C + version has been modified as follows:

#Global configuration parameters
GlobalConfig:
 DeviceNum: 3

#Equipment configuration parameters
DeviceParam:
 - ID: 1
   DeviceName: Dev_1
   DeviceIp: 192.168.2.111
   FrameRate: 24
   DepthType: 3
   FrameWidth: 1200
   FrameHeight: 1024
   TriggerInterval: 300

 - ID: 2
   DeviceName: Dev_2
   DeviceIp: 192.168.2.112
   FrameRate: 24
   DepthType: 3
   FrameWidth: 1200
   FrameHeight: 1024
   TriggerInterval: 300

 - ID: 3
   DeviceName: Dev_3
   DeviceIp: 192.168.2.113
   FrameRate: 24
   DepthType: 3
   FrameWidth: 1200
   FrameHeight: 1024
   TriggerInterval: 300

Where "- ID" represents three different arrays, which can be accessed directly in python by using the subscript of config["DeviceParam"][0]. Create a new testyaml The cpp file is read and parsed as follows:

C + + read and parse configuration file:

#include <iostream>
#include "yaml-cpp/yaml.h"
#include <fstream>

using namespace std;


typedef struct GlobalConfig
{
	int deviceNum;					
}GlbCon;


typedef struct DeviceInfo
{
	std::string DeviceName;			
	std::string DeviceIp;			
	
	int ID;							
	int FrameRate;					
	int DepthType;					
	int FrameWidth;					
	int FrameHeight;				
	int TriggerInterval;			

}DevInfo;



namespace YAML {
    template<> struct convert<GlobalConfig> {
        static Node encode(const GlobalConfig &globalconfig) {
            YAML::Node node;
            node.push_back(globalconfig.deviceNum);
            
            return node;
        }

        static bool decode(const Node &node, GlobalConfig &globalconfig) {
            globalconfig.deviceNum = node["DeviceNum"].as<int>();
            return true;
        }   
    };

	template<> struct convert<DeviceInfo> {
		static Node encode(const DeviceInfo &devInfo) {
			YAML::Node node;
			node.push_back(devInfo.DeviceName);
			node.push_back(devInfo.DeviceIp);
			node.push_back(devInfo.ID);
			
			node.push_back(devInfo.FrameRate);
			node.push_back(devInfo.DepthType);
			node.push_back(devInfo.FrameWidth);
			
			node.push_back(devInfo.FrameHeight);
			node.push_back(devInfo.TriggerInterval);
			
			return node;
	}

        static bool decode(const Node &node, DeviceInfo &devInfo) {
            devInfo.DeviceName = node["DeviceName"].as<std::string>();
            devInfo.DeviceIp = node["DeviceIp"].as<std::string>();
            devInfo.ID = node["ID"].as<int>();
            
            devInfo.FrameRate = node["FrameRate"].as<int>();
            devInfo.DepthType = node["DepthType"].as<int>();
            
            devInfo.FrameWidth = node["FrameWidth"].as<int>();
            devInfo.FrameHeight = node["FrameHeight"].as<int>();
            devInfo.TriggerInterval = node["TriggerInterval"].as<int>();
            return true;
        }
    };
}


int main(int argc,char** argv)
{
	GlobalConfig globalconfig;
    YAML::Node config = YAML::LoadFile("./config.yaml");
	std::cout << config["GlobalConfig"]["deviceNum"].as<int>() << std::endl;

    if(config["DeviceParam"])
    {
		std::vector<DevInfo> vi = config["DeviceParam"].as<std::vector<DevInfo>>();
		for (std::vector<DevInfo>::iterator it = vi.begin(); it != vi.end(); ++it) {
            std::cout << "vector: ID: " << it->ID << " name: " << it->DeviceName << std::endl;
        }
	}

    return 0;
}

The encode decode part of the code is a custom structure parsing.

C + + generate write configuration file:

	std::ofstream fout("wrYaml.yaml");
	YAML::Node configWr;
	
	configWr["GlobalConfig"]["DeviceNum"] = 5;

	configWr["DeviceParam"]["DeviceParam"][0]["ID"] = "1";
	configWr["DeviceParam"]["DeviceParam"][0]["DeviceName"] = "Dev_1";
	
	configWr["DeviceParam"]["DeviceParam"][1]["ID"] = "2";
	configWr["DeviceParam"]["DeviceParam"][1]["DeviceName"] = "Dev_2";
	fout << configWr;
	fout.close();

The contents of the written file are as follows:

GlobalConfig:
  DeviceNum: 5
DeviceParam:
  DeviceParam:
    - ID: 1
      DeviceName: Dev_1
    - ID: 2
      DeviceName: Dev_2

Note: when writing multiple arrays in C + +, the subscript can be directly assigned to the specified parameter.

Keywords: Python C++ yaml

Added by punked on Mon, 17 Jan 2022 15:27:06 +0200