[Python] processing a python yaml file tag with attribue

Discussão em 'Python' iniciado por Stack, Setembro 14, 2024.

  1. Stack

    Stack Membro Participativo

    !Employee old:
    id: some_id
    name: John
    cfg:
    param: "abc"


    I need to load update, and save a yaml file, which contains a structure, similar to the above.

    I tried using add_constructor and add_representer. WHich worked when the Tag is placed separately.

    !Employee
    old:
    id: some_id
    name: John
    cfg:
    param: "abc"


    I would like nevertheless to avoid the preporcessing of the original file. Also I dont have ruamel (suggested on other posts).

    In the example below yaml does does not seen to scan the entire structure, i.e. does not include the mapping part under the tag.

    #====================================================================

    import yaml


    # Custom class to handle !Employee old: name: Peter
    class Employee:
    def __init__(self, status, data=None):
    self.status = status # e.g., "old"
    self.data = data or {} # e.g., {'name': 'Peter'}

    def __repr__(self):
    return f"!Employee {self.status}: {self.data}"


    # Custom constructor for the !Employee tag
    def employee_constructor(loader, node):
    # Check if the node is a MappingNode
    print(f"EMPL_CONST node: {node}")
    if isinstance(node, yaml.MappingNode):
    # Expecting only one key-value pair (e.g., "old": {"name": "Peter"})
    print(f"EMPL_CONST node: {node.value[0]}")
    first_key_node, value_node = node.value[0]

    # The key is the scalar "old"
    status = loader.construct_scalar(first_key_node)

    # The value is the mapping part {"name": "Peter"}
    data = loader.construct_mapping(value_node)

    # Return an Employee object with the status and data
    return Employee(status, data)

    raise yaml.constructor.ConstructorError(None, None, f"Unexpected node type: {type(node)}", node.start_mark)


    # Custom representer for the !Employee tag
    def employee_representer(dumper, data):
    # Create a tag with the status (e.g., !Employee old)

    tag = f"!Employee"
    return dumper.represent_mapping(tag, {data.status: data.data})

    # Register the custom constructor and representer
    yaml.add_constructor('!Employee', employee_constructor)
    yaml.add_representer(Employee, employee_representer)

    def load_yaml(file_path):
    with open(file_path, 'r') as file:
    data = yaml.load(file, Loader=yaml.FullLoader)
    # print(data)
    return data
    def save_yaml(file_path, data):
    with open(file_path, 'w') as file:
    yaml.dump(data, file, default_flow_style=False)

    # Testing the code
    if __name__ == "__main__":
    yaml_string = """
    !Employee old:
    name: Some_Name
    id: some_id

    cfg:
    param : 'abc'
    """

    # Load the YAML data`your text`
    data = yaml.load(yaml_string, Loader=yaml.FullLoader)
    # data = load_yaml("input3.yaml")
    print("Loaded YAML data:")
    print(data)

    # Modify the data (optional)
    data['cfg']['param'] = 'xyz'

    # Dump the data back to YAML format
    output = yaml.dump(data, default_flow_style=False)
    print("\nModified YAML output:")
    print(output)
    save_yaml("output3.yaml", data)

    Continue reading...

Compartilhe esta Página