【问题标题】:How to create dynamic YAML string如何创建动态 YAML 字符串
【发布时间】:2017-03-21 17:22:12
【问题描述】:

我有一个 YAML 文件

tests:
  - is-gt: val, 2
    info: "Test Succeeded!!, val is greater than 2, it is <{{post['val']}}>"
    err: "Test Failed!!, val is not greater than 2, it is <{{post['val']}}>"

在这种情况下,它应该直接取操作“is-gt”指定的值,而不是 val(即 2 )的硬编码值。 如果我将测试操作更改为 "is-gt: val, 3" ,它应该会在信息和错误消息中自动获取此值。

我该怎么做?我在一些 Python 脚本中进一步使用这个 YAML 文件来读取它。

【问题讨论】:

标签: python yaml templating string-interpolation


【解决方案1】:

您的 is-gt 只是 YAML 的标量字符串,用作映射的键​​。该字符串没有什么特别之处,当然也不是“操作”。

您可以对加载的 YAML 进行后处理(例如,如果您使用来自 ruamel.yaml/PyYAML 的 safe_load)。更干净的 YAML 是您标记序列项,并基于该标记将映射键/值加载到解释 is-gt 的特定对象中,并更新成为其属性的其他值的标量字符串。

这样的对象最好有一个类似地图的界面,您必须决定在加载时进行解析,或者在通过其键检索值时使用惰性求值。

【讨论】:

    【解决方案2】:

    YAML 是一种数据序列化语言,而不是一种数据处理语言。模板功能超出了它的范围(尽管在该方向上存在一些可选功能,但在此不适用)。

    已经提议使用其他模板语言进行后处理。我想添加使用 pystache 的建议,因为它是一种最小语言,在这里可能比使用 Jinja 更合适。

    此外,我建议将值规范放入地图中。而且由于您已经将 {{ 用于字符串中的其他内容,我建议告诉 pystache 使用另一种转义方式。示例:

    tests:
      - is-gt: {val: 2}
        info: "Test Succeeded!!, val is greater than `val`, it is <{{post['val']}}>"
        err: "Test Failed!!, val is not greater than `val`, it is <{{post['val']}}>"
    

    您现在可以像这样解析它:

    import yaml, pystache
    
    raw = yaml.safe_load("""
    tests:
      - is-gt: {val: 2}
        info: "Test Succeeded!!, val is greater than `val`, it is <{{post['val']}}>"
        err: "Test Failed!!, val is not greater than `val`, it is <{{post['val']}}>"
    """)
    
    def dynString(inputs, template):
        return pystache.render("{{=` `=}}" + template, inputs)
    
    tests = []
    for rawtest in raw["tests"]:
        test = {}
        inputs = rawtest["is-gt"]
        for msg in ["info", "err"]:
            test[msg] = dynString(inputs, rawtest[msg])
        tests.append(test)
    
    print(tests)
    

    哪些输出:

    [{'info': "Test Succeeded!!, val is greater than 2, it is <{{post['val']}}>",
      'err': "Test Failed!!, val is not greater than 2, it is <{{post['val']}}>"}]
    

    【讨论】:

    • 您的输出中仍有post['val']。乍一看,我认为您必须填充post 而不是inputs,但我没有使用pystache(所以我可能错了)。
    • Anthon:我相信这就是我们想要的,因为post['val'] 访问的是要比较的实际值,而{val: 2} 指定要比较的值。但我可能是错的,从问题中不是很清楚。有人问我如何用 YAML 中给出的值替换 2,我做了。
    • 我错过了在您的单独输入中将2 替换为val,可能是因为您仍然使用实际safe_load() 的多行字符串中的硬编码2 而不是使用反引号@987654336 @。如果你在is-gt 的值中更改23,则不会发生任何事情。
    • 哦,是的,我监督了这一点。感谢修复。
    • @flyx 感谢您的解决方案,但如果 {val: 2} 是 {//val :2} 并且剩下的 val
    猜你喜欢
    • 2012-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-16
    相关资源
    最近更新 更多