Hướng dẫn load yaml file python

I made my own script for this. Feel free to use it, as long as you keep the attribution. The script can parse yaml from a file [function load], parse yaml from a string [function loads] and convert a dictionary into yaml [function dumps]. It respects all variable types.

# © didlly AGPL-3.0 License - github.com/didlly

def is_float[string: str] -> bool:
    try:
        float[string]
        return True
    except ValueError:
        return False


def is_integer[string: str] -> bool:
    try:
        int[string]
        return True
    except ValueError:
        return False


def load[path: str] -> dict:
    with open[path, "r"] as yaml:
        levels = []
        data = {}
        indentation_str = ""

        for line in yaml.readlines[]:
            if line.replace[line.lstrip[], ""] != "" and indentation_str == "":
                indentation_str = line.replace[line.lstrip[], ""].rstrip["\n"]
            if line.strip[] == "":
                continue
            elif line.rstrip[][-1] == ":":
                key = line.strip[][:-1]
                quoteless = [
                    is_float[key]
                    or is_integer[key]
                    or key == "True"
                    or key == "False"
                    or ["[" in key and "]" in key]
                ]

                if len[line.replace[line.strip[], ""]] // 2 < len[levels]:
                    if quoteless:
                        levels[len[line.replace[line.strip[], ""]] // 2] = f"[{key}]"
                    else:
                        levels[len[line.replace[line.strip[], ""]] // 2] = f"['{key}']"
                else:
                    if quoteless:
                        levels.append[f"[{line.strip[][:-1]}]"]
                    else:
                        levels.append[f"['{line.strip[][:-1]}']"]
                if quoteless:
                    exec[
                        f"data{''.join[str[i] for i in levels[:line.replace[line.lstrip[], ''].count[indentation_str] if indentation_str != '' else 0]]}[{key}]"
                        + " = {}"
                    ]
                else:
                    exec[
                        f"data{''.join[str[i] for i in levels[:line.replace[line.lstrip[], ''].count[indentation_str] if indentation_str != '' else 0]]}['{key}']"
                        + " = {}"
                    ]

                continue

            key = line.split[":"][0].strip[]
            value = ":".join[line.split[":"][1:]].strip[]

            if [
                is_float[value]
                or is_integer[value]
                or value == "True"
                or value == "False"
                or ["[" in value and "]" in value]
            ]:
                if [
                    is_float[key]
                    or is_integer[key]
                    or key == "True"
                    or key == "False"
                    or ["[" in key and "]" in key]
                ]:
                    exec[
                        f"data{'' if line == line.strip[] else ''.join[str[i] for i in levels[:line.replace[line.lstrip[], ''].count[indentation_str] if indentation_str != '' else 0]]}[{key}] = {value}"
                    ]
                else:
                    exec[
                        f"data{'' if line == line.strip[] else ''.join[str[i] for i in levels[:line.replace[line.lstrip[], ''].count[indentation_str] if indentation_str != '' else 0]]}['{key}'] = {value}"
                    ]
            else:
                if [
                    is_float[key]
                    or is_integer[key]
                    or key == "True"
                    or key == "False"
                    or ["[" in key and "]" in key]
                ]:
                    exec[
                        f"data{'' if line == line.strip[] else ''.join[str[i] for i in levels[:line.replace[line.lstrip[], ''].count[indentation_str] if indentation_str != '' else 0]]}[{key}] = '{value}'"
                    ]
                else:
                    exec[
                        f"data{'' if line == line.strip[] else ''.join[str[i] for i in levels[:line.replace[line.lstrip[], ''].count[indentation_str] if indentation_str != '' else 0]]}['{key}'] = '{value}'"
                    ]
    return data


def loads[yaml: str] -> dict:
    levels = []
    data = {}
    indentation_str = ""

    for line in yaml.split["\n"]:
        if line.replace[line.lstrip[], ""] != "" and indentation_str == "":
            indentation_str = line.replace[line.lstrip[], ""]
        if line.strip[] == "":
            continue
        elif line.rstrip[][-1] == ":":
            key = line.strip[][:-1]
            quoteless = [
                is_float[key]
                or is_integer[key]
                or key == "True"
                or key == "False"
                or ["[" in key and "]" in key]
            ]

            if len[line.replace[line.strip[], ""]] // 2 < len[levels]:
                if quoteless:
                    levels[len[line.replace[line.strip[], ""]] // 2] = f"[{key}]"
                else:
                    levels[len[line.replace[line.strip[], ""]] // 2] = f"['{key}']"
            else:
                if quoteless:
                    levels.append[f"[{line.strip[][:-1]}]"]
                else:
                    levels.append[f"['{line.strip[][:-1]}']"]
            if quoteless:
                exec[
                    f"data{''.join[str[i] for i in levels[:line.replace[line.lstrip[], ''].count[indentation_str] if indentation_str != '' else 0]]}[{key}]"
                    + " = {}"
                ]
            else:
                exec[
                    f"data{''.join[str[i] for i in levels[:line.replace[line.lstrip[], ''].count[indentation_str] if indentation_str != '' else 0]]}['{key}']"
                    + " = {}"
                ]

            continue

        key = line.split[":"][0].strip[]
        value = ":".join[line.split[":"][1:]].strip[]

        if [
            is_float[value]
            or is_integer[value]
            or value == "True"
            or value == "False"
            or ["[" in value and "]" in value]
        ]:
            if [
                is_float[key]
                or is_integer[key]
                or key == "True"
                or key == "False"
                or ["[" in key and "]" in key]
            ]:
                exec[
                    f"data{'' if line == line.strip[] else ''.join[str[i] for i in levels[:line.replace[line.lstrip[], ''].count[indentation_str] if indentation_str != '' else 0]]}[{key}] = {value}"
                ]
            else:
                exec[
                    f"data{'' if line == line.strip[] else ''.join[str[i] for i in levels[:line.replace[line.lstrip[], ''].count[indentation_str] if indentation_str != '' else 0]]}['{key}'] = {value}"
                ]
        else:
            if [
                is_float[key]
                or is_integer[key]
                or key == "True"
                or key == "False"
                or ["[" in key and "]" in key]
            ]:
                exec[
                    f"data{'' if line == line.strip[] else ''.join[str[i] for i in levels[:line.replace[line.lstrip[], ''].count[indentation_str] if indentation_str != '' else 0]]}[{key}] = '{value}'"
                ]
            else:
                exec[
                    f"data{'' if line == line.strip[] else ''.join[str[i] for i in levels[:line.replace[line.lstrip[], ''].count[indentation_str] if indentation_str != '' else 0]]}['{key}'] = '{value}'"
                ]

    return data


def dumps[yaml: dict, indent=""] -> str:
    """A procedure which converts the dictionary passed to the procedure into it's yaml equivalent.

    Args:
        yaml [dict]: The dictionary to be converted.

    Returns:
        data [str]: The dictionary in yaml form.
    """

    data = ""

    for key in yaml.keys[]:
        if type[yaml[key]] == dict:
            data += f"\n{indent}{key}:\n"
            data += dumps[yaml[key], f"{indent}  "]
        else:
            data += f"{indent}{key}: {yaml[key]}\n"

    return data


print[load["config.yml"]]

Example

config.yml

level 0 value: 0

level 1:
  level 1 value: 1
  level 2:
    level 2 value: 2

level 1 2:
  level 1 2 value: 1 2
  level 2 2:
    level 2 2 value: 2 2

Output

{'level 0 value': 0, 'level 1': {'level 1 value': 1, 'level 2': {'level 2 value': 2}}, 'level 1 2': {'level 1 2 value': '1 2', 'level 2 2': {'level 2 2 value': 2 2}}}

Chủ Đề