Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jsp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何通过字典递归并动态更新值,以便以后可以引用它们?_Python_Json_Dictionary_Recursion_Yaml - Fatal编程技术网

Python 如何通过字典递归并动态更新值,以便以后可以引用它们?

Python 如何通过字典递归并动态更新值,以便以后可以引用它们?,python,json,dictionary,recursion,yaml,Python,Json,Dictionary,Recursion,Yaml,我正在尝试编写一个配置变量引擎,该引擎接受YAML文件(包含AWS配置变量)作为输入,并将其转换为JSON,以便可以将其上载到HTTP k/v API(如concur)。一个让我感到困惑的特性将允许开发人员在后续的键中“包括”键集(用下划线标识,在最终有效负载中省略)。示例如下: # Region us-east-1: # Any key preceded by an underscore (_) is considered a "tag group" and will not be upl

我正在尝试编写一个配置变量引擎,该引擎接受YAML文件(包含AWS配置变量)作为输入,并将其转换为JSON,以便可以将其上载到HTTP k/v API(如concur)。一个让我感到困惑的特性将允许开发人员在后续的键中“包括”键集(用下划线标识,在最终有效负载中省略)。示例如下:

# Region
us-east-1:
  # Any key preceded by an underscore (_) is considered a "tag group" and will not be uploaded to Consul KV unless explicitly included.
  _taggroup1:
    key1: value1
    key2: value2
    key3: value3
  _taggroup2:
    key4: value1
    key5: value2
    key6: value3

  dev:
    _include: us-east-1/_taggroup1
  qa:
    _include:
      - us-east-1/_taggroup1
      - us-east-1/_taggroup2
    key6: baz
  prod:
    _include:
      - us-east-1/_taggroup1
      - us-east-1/_taggroup2

us-west-1:
  _taggroup1:
    key1: value1
    key2: value2
    key3: value3
  _taggroup2:
    key4: value1
    key5: value2
    key6: value3

  dev:
    _include:
      - us-west-1/_taggroup1
  qa:
    _include:
      - us-west-1/_taggroup1
      - us-west-1/_taggroup2
    key2: foo
  prod:
    _include:
      - us-west-1/_taggroup1
      - us-west-1/_taggroup2
    key4: foo
    key5: bar
    key1: undef

  us-west-1a:
    qa:
      _include: us-west-1/qa
    prod:
      _include: us-west-1/prod

  us-west-1b:
    _include: us-west-1/us-west-1a
如您所见,我正在尝试构造一个配置文件,允许开发人员对变量进行分组,并在他们愿意的情况下包含/覆盖它们

到目前为止,我为本实验编写的代码基本上是您的标准递归函数,其中添加了特定于此应用程序的内容:

# parse_input is a separate function that converts a YAML stream into
# an OrderedDict
original_dict = parse_input(stream1)

def print_dict(input_dict):

    new_dict = collections.OrderedDict()

    for key, value in input_dict.iteritems():
        if key.startswith('_'):
            if key == '_include':
                if isinstance(value, list):
                    for item in value:
                        x = dpath.util.get(original_dict, item)
                        for k, v in x.iteritems():
                            new_dict[k] = v
                else:
                    x = dpath.util.get(original_dict, value)
                    for k, v in x.iteritems():
                        new_dict[k] = v
            else:
                continue
            continue
        elif isinstance(value, dict):
            new_dict[key] = print_dict(value)
        else:
            new_dict[key] = value
    return new_dict
到目前为止,我取得的成果如下:

{
    "us-east-1": {
        "dev": {
            "key1": "value1", 
            "key2": "value2", 
            "key3": "value3"
        }, 
        "qa": {
            "key1": "value1", 
            "key2": "value2", 
            "key3": "value3", 
            "key4": "value1", 
            "key5": "value2", 
            "key6": "baz"
        }, 
        "prod": {
            "key1": "value1", 
            "key2": "value2", 
            "key3": "value3", 
            "key4": "value1", 
            "key5": "value2", 
            "key6": "value3"
        }
    }, 
    "us-west-1": {
        "dev": {
            "key1": "value1", 
            "key2": "value2", 
            "key3": "value3"
        }, 
        "qa": {
            "key1": "value1", 
            "key2": "foo", 
            "key3": "value3", 
            "key4": "value1", 
            "key5": "value2", 
            "key6": "value3"
        }, 
        "prod": {
            "key1": "undef", 
            "key2": "value2", 
            "key3": "value3", 
            "key4": "foo", 
            "key5": "bar", 
            "key6": "value3"
        }, 
        "us-west-1a": {
            "qa": {
                "_include": [
                    "us-west-1/_taggroup1", 
                    "us-west-1/_taggroup2"
                ], 
                "key2": "foo"
            }, 
            "prod": {
                "_include": [
                    "us-west-1/_taggroup1", 
                    "us-west-1/_taggroup2"
                ], 
                "key4": "foo", 
                "key5": "bar", 
                "key1": "undef"
            }
        }, 
        "us-west-1b": {
            "qa": {
                "_include": "us-west-1/qa"
            }, 
            "prod": {
                "_include": "us-west-1/prod"
            }
        }
    }
}
正如你所看到的,我似乎已经到了一半。我的问题是,在最初的实验中,我在引用包含集时引用函数中的
original_dict
变量(使用
dpath
返回键),得到了良好的结果。这很快就会变成一个问题,因为函数递归更深(即,在本例中是AZ特定变量),因为我不知道如何动态更新原始dict中的键,或者以其他方式跟踪更改,因此函数将注入一个带有
\u include
键的键集,并且无法重新计算它们


我如何消除依赖于引用原始词典的情况,而是动态跟踪更改,以便在树的更深处正确地计算
\u include
键?

我认为此代码解决了您所面临的问题。关键的变化是递归到
print_dict
,结果来自
dpath
。我还折叠了一些冗余代码

代码:

import yaml
import collections
import json
import dpath

with open('data.yml', 'rb') as f:
    original_dict = yaml.load(f)

def print_dict(input_dict):

    new_dict = collections.OrderedDict()

    for key, value in input_dict.iteritems():
        if key.startswith('_'):
            if key == '_include':
                if not isinstance(value, list):
                    value = [value]
                for item in value:
                    x = print_dict(dpath.util.get(original_dict, item))
                    for k, v in x.iteritems():
                        new_dict[k] = v
        elif isinstance(value, dict):
            new_dict[key] = print_dict(value)
        else:
            new_dict[key] = value
    return new_dict

print(json.dumps(print_dict(original_dict), indent=2))
{
  "us-east-1": {
    "qa": {
      "key3": "value3", 
      "key2": "value2", 
      "key1": "value1", 
      "key6": "baz", 
      "key5": "value2", 
      "key4": "value1"
    }, 
    "prod": {
      "key3": "value3", 
      "key2": "value2", 
      "key1": "value1", 
      "key6": "value3", 
      "key5": "value2", 
      "key4": "value1"
    }, 
    "dev": {
      "key3": "value3", 
      "key2": "value2", 
      "key1": "value1"
    }
  }, 
  "us-west-1": {
    "qa": {
      "key2": "value2", 
      "key3": "value3", 
      "key1": "value1", 
      "key6": "value3", 
      "key5": "value2", 
      "key4": "value1"
    }, 
    "us-west-1b": {
      "qa": {
        "key2": "value2", 
        "key3": "value3", 
        "key1": "value1", 
        "key6": "value3", 
        "key5": "value2", 
        "key4": "value1"
      }, 
      "prod": {
        "key1": "value1", 
        "key3": "value3", 
        "key2": "value2", 
        "key6": "value3", 
        "key5": "bar", 
        "key4": "foo"
      }
    }, 
    "prod": {
      "key1": "value1", 
      "key3": "value3", 
      "key2": "value2", 
      "key6": "value3", 
      "key5": "bar", 
      "key4": "foo"
    }, 
    "us-west-1a": {
      "qa": {
        "key2": "value2", 
        "key3": "value3", 
        "key1": "value1", 
        "key6": "value3", 
        "key5": "value2", 
        "key4": "value1"
      }, 
      "prod": {
        "key1": "value1", 
        "key3": "value3", 
        "key2": "value2", 
        "key6": "value3", 
        "key5": "bar", 
        "key4": "foo"
      }
    }, 
    "dev": {
      "key3": "value3", 
      "key2": "value2", 
      "key1": "value1"
    }
  }
}
输出:

import yaml
import collections
import json
import dpath

with open('data.yml', 'rb') as f:
    original_dict = yaml.load(f)

def print_dict(input_dict):

    new_dict = collections.OrderedDict()

    for key, value in input_dict.iteritems():
        if key.startswith('_'):
            if key == '_include':
                if not isinstance(value, list):
                    value = [value]
                for item in value:
                    x = print_dict(dpath.util.get(original_dict, item))
                    for k, v in x.iteritems():
                        new_dict[k] = v
        elif isinstance(value, dict):
            new_dict[key] = print_dict(value)
        else:
            new_dict[key] = value
    return new_dict

print(json.dumps(print_dict(original_dict), indent=2))
{
  "us-east-1": {
    "qa": {
      "key3": "value3", 
      "key2": "value2", 
      "key1": "value1", 
      "key6": "baz", 
      "key5": "value2", 
      "key4": "value1"
    }, 
    "prod": {
      "key3": "value3", 
      "key2": "value2", 
      "key1": "value1", 
      "key6": "value3", 
      "key5": "value2", 
      "key4": "value1"
    }, 
    "dev": {
      "key3": "value3", 
      "key2": "value2", 
      "key1": "value1"
    }
  }, 
  "us-west-1": {
    "qa": {
      "key2": "value2", 
      "key3": "value3", 
      "key1": "value1", 
      "key6": "value3", 
      "key5": "value2", 
      "key4": "value1"
    }, 
    "us-west-1b": {
      "qa": {
        "key2": "value2", 
        "key3": "value3", 
        "key1": "value1", 
        "key6": "value3", 
        "key5": "value2", 
        "key4": "value1"
      }, 
      "prod": {
        "key1": "value1", 
        "key3": "value3", 
        "key2": "value2", 
        "key6": "value3", 
        "key5": "bar", 
        "key4": "foo"
      }
    }, 
    "prod": {
      "key1": "value1", 
      "key3": "value3", 
      "key2": "value2", 
      "key6": "value3", 
      "key5": "bar", 
      "key4": "foo"
    }, 
    "us-west-1a": {
      "qa": {
        "key2": "value2", 
        "key3": "value3", 
        "key1": "value1", 
        "key6": "value3", 
        "key5": "value2", 
        "key4": "value1"
      }, 
      "prod": {
        "key1": "value1", 
        "key3": "value3", 
        "key2": "value2", 
        "key6": "value3", 
        "key5": "bar", 
        "key4": "foo"
      }
    }, 
    "dev": {
      "key3": "value3", 
      "key2": "value2", 
      "key1": "value1"
    }
  }
}

这似乎有效!谢谢,我(显然)还没有试过!:)