【问题标题】:How can I evaluate algebraic expressions defined in YAML?如何评估 YAML 中定义的代数表达式?
【发布时间】:2018-12-13 15:41:15
【问题描述】:

我有以下两个单独的 YAML 文件。

  • val.yaml:这里定义了变量
  • expr.yaml:这里定义了表达式

val.yaml

x: 2
y: 3
z: 5

expr.yaml

result: (x + y) * z

parse.py

import yaml

with open('val.yaml', 'r') as stream:
    val = yaml.load(stream)

with open('expr.yaml', 'r') as stream:
    expr = yaml.load(stream)

....

# this should be (2 + 3) * 5 = 25
print expr['result']

如何通过引用val.yaml 中定义的变量来评估expr.yaml 中定义的表达式?

【问题讨论】:

    标签: python parsing yaml


    【解决方案1】:

    您可以使用sympy 轻松做到这一点:

    from __future__ import print_function
    
    import ruamel.yaml
    from sympy.parsing.sympy_parser import parse_expr
    
    yaml = ruamel.yaml.YAML(typ='safe')
    with open('var.yaml') as stream:
        vars = yaml.load(stream)
    with open('expr.yaml') as stream:
        expr = yaml.load(stream)
    
    for k in expr:
        l = parse_expr(expr[k], vars)
        print('{}: {}'.format(k, l))
    

    哪个打印(使用 Python 2 或 3):

    result: 25
    
    • 你应该真正开始使用print 作为一个函数,即使你被Python 2.7 卡住了,因此导入了from __future__。带有 print 语句的 Python 2.7 计划在两年内停止使用,因此请使用此类向前兼容的导入并习惯使用它们。
    • 您不应该使用 PyYAML 的yaml.load(),因为它可能是不安全的,当然如果其他人编辑您的输入文件。要么使用yaml.safe_load(),要么使用上面的(加载速度也更快)。

    【讨论】:

      【解决方案2】:

      这是一种实现方式,即使我强烈不鼓励在生产环境中使用这种方法(应避免使用eval,应清理输入等...)。这个想法是执行 s 替换,迭代 yaml 中的变量,假设表达式 yaml(在result)遵循相同的命名约定。这是一个示例:

      #!/usr/bin/env python
      
      import yaml
      
      VARS_YAML = """
      x: 2
      y: 3
      z: 5
      """
      
      EXPR_YAML = """
      result: (x + y) * z
      """
      
      vars = yaml.load(VARS_YAML)
      expr = yaml.load(EXPR_YAML)
      
      for key, value in vars.items(): # for python2: vars.iteritems()
        expr['result'] = expr['result'].replace(key, str(value))
      
      r = eval(expr['result'])
      print(r) # for python2: print r
      # => 25
      

      此代码适用于 python-3(我目前唯一可用的版本),但将其移至 python-2(我认为是您的版本)很简单。如果您更喜欢从文件中加载 yaml:

      with open('var.yaml', 'r') as var_file:
        vars = yaml.load(var_file)
      

      绰绰有余。

      【讨论】:

        猜你喜欢
        • 2011-02-08
        • 1970-01-01
        • 1970-01-01
        • 2013-06-20
        • 2016-05-04
        • 1970-01-01
        • 1970-01-01
        • 2020-01-26
        相关资源
        最近更新 更多