Reputation: 735
I have the following two separate YAML files.
val.yaml
: variables are defined hereexpr.yaml
: expressions are defined hereval.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']
How can I evaluate expressions defined in expr.yaml
by referencing variables defined in val.yaml
?
Upvotes: 2
Views: 6192
Reputation: 76792
You can most easily do this with 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))
which prints (using Python 2 or 3):
result: 25
print
as a function, even if you are stuck with Python 2.7, hence the from __future__
import. Python 2.7 with its print statement is planned to be end-of-life in two years, so use such forward compatibility imports and get accustomed to using them.yaml.load()
as it can be unsafe, certainly if someone else edits your input files. Either use yaml.safe_load()
or use the above (which loads faster as well).Upvotes: 2
Reputation: 2954
This is a way of doing it, even if I strongly discourage this approach in a production situation (eval
should be avoided, input should be sanitized, etc...). The idea is to perform s substitution, iterating over the variables in the yaml, under the hypothesis that the expression yaml (in result
) follows the same naming convention. Here a sample:
#!/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
This code is for python-3 (the only version I have available at the moment), but it is simple to move it to python-2 (that I think is your version). If you prefer to load the yaml from a file:
with open('var.yaml', 'r') as var_file:
vars = yaml.load(var_file)
is more than enough.
Upvotes: 0