动态更新复杂的OrderedDict(基于yaml文件)

时间:2018-02-23 19:35:53

标签: python config ordereddictionary

我正在尝试构建一个依赖于非常动态配置的软件(或者#34;规则集",真的)。我试图用伪代码捕获它:

"""
---
config:
  item1:
    thething: ${stages.current.variables.item1}

stages:
  dev:
    variables:
      item1: stuff
  prod:
    variables:
      item1: stuf2
"""


config_obj = yaml.load(config)
current_stage = 'dev'
#Insert artificial "current stage" to allow var matching
stages['current'] = stages[current_stage]
updated_config_obj = replace_vars(config_obj)

目标是让updated_config_obj将所有变量类型替换为实际值,因此对于此示例,它应将${stages.current.variables.item1}替换为stuff。通过将当前阶段中的任何内容复制到同一OrderedDict中的current项中,可以轻松解决current部分,但我仍然对如何实际执行替换感到困惑。配置yaml可能非常大,完全依赖于插件系统,因此必须是动态的。

现在我正在看着"行走"整个对象,检查每个"叶子上是否存在$" (表示变量)并对当前对象执行查找备份以解决"解决"变量,但不知何故,似乎过于复杂。另一种选择是(我猜)你可以在#34;配置字符串"上使用解析对象作为查找。当然可行,但它感觉有点脏。

我觉得应该有一个更优雅的解决方案,只能在解析的对象上完成(不与字符串交互),但它逃脱了我。

任何指示赞赏!

1 个答案:

答案 0 :(得分:0)

首先,我的两分钱:尽量避免在配置文件中使用任何形式的插值。这会创建另一层依赖项 - 程序的一个依赖项(配置文件)和配置文件的另一个依赖项。

目前它是一个灵活的解决方案,但考虑到未来五年,一些低级开发人员可能会盯着${stages.current.variables.item1}一个月试图弄清楚这是什么,而不是理解这是隐含的映射到stages.dev。然后更糟糕的是,一些其他开发人员出现了,并且看到插值的闸门已经打开,他们开始使用{{stages_dev}},意味着某些值应该从系统的环境变量中插入。然后其他一些开发人员开始使用他们自己的约定,如{{!stagesdev!}},这意味着该值使用自己的自定义运行时插值,在一些不起眼的下游后巷中调用。

然后聘请了一些顾问对整件事进行逆向工程,现在他们正在意大利海上航行。

如果您仍想这样做,我建议打开/解析配置文件到字典中(大概使用yaml.load()),然后逐行遍历整个事物,使用正则表达式查找\$\{(.*)\}的实例。

对于每个捕获的组,创建一个有序列表,如:

# ["stages", "current", "variables", item1"]
yaml_references = ".".split("stages.current.variables.item1")

然后,您可以执行以下操作:

yaml_config_dict = "" # the parsed configuration file
interpolated_reference = None

for y in yaml_references:
    interpolated_reference = yaml_config_dict[y]

i = interpolated_reference[0]

现在i应该表示在.yaml文件的上下文中指向的任何${stages.current.variables.item1},您应该能够进行字符串替换。