递归函数用于读取 YAML 文件,查找包含其他 YAML 文件的键。

huangapple go评论60阅读模式
英文:

Recursive function to read yaml files looking for a key which includes other yaml files

问题

我正在尝试编写一个函数,该函数读取一个 YAML 文件并查找特定的键。如果该键不存在,该函数应该检查是否存在 "_include" 键,然后检查该 YAML 文件,直到所有选项都尝试完毕或找到该键。

import yaml
import os.path

def load_yaml_data(yaml_path):
    """读取 YAML 文件并返回数据"""
    try:
        with open(yaml_path, 'r', encoding="utf-8") as yaml_file:
            yaml_data = yaml.safe_load(yaml_file)
            return yaml_data
    except FileNotFoundError:
        return None
    except yaml.YAMLError as exc:
        return None

def find_key_in_yaml_recursive(yaml_path, key):
    print(f"打开 {yaml_path}")
    yaml_data = load_yaml_data(yaml_path)
    if yaml_data:
        if key in yaml_data:
            print(f"{key}{yaml_path} 中找到")
            return yaml_path
        elif '_include' in yaml_data:
            for include in yaml_data['_include']:
                include_path = os.path.expandvars(include)
                if not os.path.isabs(include_path):
                    include_path = os.path.abspath('/'.join([os.path.dirname(yaml_path), include_path]))
                result = find_key_in_yaml_recursive(include_path, key)
                if result:
                    return result

if __name__ == "__main__":
    print(find_key_in_yaml_recursive("./test.yaml", "foo"))

目录结构:

.
|    test.yaml
└─── test
│   │    test.yaml
│   └─── deeper
│       │   test.yaml
│       │   notexist.yaml

./test.yaml

---
_include:
  - "test/test.yaml"
not_foo:
  - "some data"

./test/test.yaml

---
_include:
  - ./deeper/notexist.yaml
  - ./deeper/test.yaml
foop:
  - "somedata"

./test/deeper/notexist.yaml

---
nothinguseful:
  - data

./test/deeper/test.yaml

---
foo:
 - some data
somethingelse:
  - data

'foo' 存在于 ./test/deeper/test.yaml 中。在大多数情况下,该函数将找到它并返回完整的 ./test/deeper/test.yaml 路径。但是,当 ./test/test.yaml 具有一个列出 deeper/notexist.yaml 在 deeper/test.yaml 之前的 "_include" 数组时,该函数返回 None。

我并没有进行太多的递归编程,但我知道你需要一个基本情况,但不确定如何在这种情况下实现基本情况。

英文:

I am attempting to write a function that reads a yaml file looking for a certain key. if the key does not exist, the function should check for an '_include' key and then check that yaml file for the same key until all options are exhausted or it finds the key.

import yaml
import os.path

def load_yaml_data(yaml_path):
    """Read a YAML file and return the data"""
    try:
        with open(yaml_path, 'r', encoding="utf-8") as yaml_file:
            yaml_data = yaml.safe_load(yaml_file)
            return yaml_data
    except FileNotFoundError:
        return None
    except yaml.YAMLError as exc:
        return None

def find_key_in_yaml_recursive(yaml_path, key):
    print(f"opening {yaml_path}")
    yaml_data = load_yaml_data(yaml_path)
    # print(f"Yaml data : {yaml_data}")
    if yaml_data:
        if key in yaml_data:
            print(f"{key} found in {yaml_path}")
            return yaml_path
        elif '_include' in yaml_data:
            for include in yaml_data['_include']:
                include_path = os.path.expandvars(include)
                if not os.path.isabs(include_path):
                    include_path = os.path.abspath('/'.join([os.path.dirname(yaml_path), include_path]))
                return find_key_in_yaml_recursive(include_path, key)

if __name__ == "__main__":
    print(find_key_in_yaml_recursive("./test.yaml", "foo"))

Dir structure:

.
|    test.yaml
└─── test
│   │    test.yaml
│   └─── deeper
│       │   test.yaml
│       │   notexist.yaml

./test.yaml

---
_include:
  - "test/test.yaml"
not_foo:
  - "some data"

./test/test.yaml

---
_include:
  - ./deeper/notexist.yaml
  - ./deeper/test.yaml
foop:
  - "somedata"

./test/deeper/notexist.yaml

---
nothinguseful:
  - data

./test/deeper/test.yaml

---
foo:
 - some data
somethingelse:
  - data

'foo' exists in ./test/deeper/test.yaml. In most circumstances, the function will find it and return the full ./test/deeper/test.yaml path. However, when ./test/test.yaml has an '_include' array that lists deeper/notexist.yaml before deeper/test.yaml the function returns None.
I have not done much recursive programming but i know you need a base case but i am unsure how to implement a base case in this scenario.

答案1

得分: 1

我认为这应该可以工作:

import yaml
import os.path

def load_yaml_data(yaml_path):
    """读取一个YAML文件并返回数据"""
    try:
        with open(yaml_path, 'r', encoding="utf-8") as yaml_file:
            yaml_data = yaml.safe_load(yaml_file)
            return yaml_data
    except FileNotFoundError:
        return None
    except yaml.YAMLError as exc:
        return None

def find_key_in_yaml_recursive(yaml_path, key):
    print(f"打开 {yaml_path}")
    yaml_data = load_yaml_data(yaml_path)
    # print(f"Yaml数据 : {yaml_data}")
    if yaml_data:
        if key in yaml_data:
            print(f"{key}{yaml_path} 中找到")
            return yaml_path
        elif '_include' in yaml_data:
            for include in yaml_data['_include']:
                include_path = os.path.expandvars(include)
                if not os.path.isabs(include_path):
                    include_path = os.path.abspath('/'.join([os.path.dirname(yaml_path), include_path]))
                var = find_key_in_yaml_recursive(include_path, key)
                if var:
                    return var
    return None

if __name__ == "__main__":
    print(find_key_in_yaml_recursive("./test.yaml", "foo"))
英文:

I think this should work:

import yaml
import os.path

def load_yaml_data(yaml_path):
    """Read a YAML file and return the data"""
    try:
        with open(yaml_path, 'r', encoding="utf-8") as yaml_file:
            yaml_data = yaml.safe_load(yaml_file)
            return yaml_data
    except FileNotFoundError:
        return None
    except yaml.YAMLError as exc:
        return None

def find_key_in_yaml_recursive(yaml_path, key):
    print(f"opening {yaml_path}")
    yaml_data = load_yaml_data(yaml_path)
    #print(f"Yaml data : {yaml_data}")
    if yaml_data:
        if key in yaml_data:
            print(f"{key} found in {yaml_path}")
            return yaml_path
        elif '_include' in yaml_data:
            for include in yaml_data['_include']:
                include_path = os.path.expandvars(include)
                if not os.path.isabs(include_path):
                    include_path = os.path.abspath('/'.join([os.path.dirname(yaml_path), include_path]))
                var = find_key_in_yaml_recursive(include_path, key)
                if var:
                    return var  
    return None

if __name__ == "__main__":
    print(find_key_in_yaml_recursive("./test.yaml", "foo"))

huangapple
  • 本文由 发表于 2023年3月7日 21:59:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/75662943.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定