How-To Guides

How to Perform Arithmetic Using eval as a Resolver

Sometimes it is necessary to perform arithmetic based on settings from your app’s config. You can register Python’s builtins.eval function as a resolver to perform simple computations.

Warning

Python’s eval can execute arbitrary code. Only use this pattern with trusted config input. Do not register or expose an eval resolver for configs that may be supplied or modified by untrusted users.

First, register the builtins.eval function as a new resolver:

>>> from omegaconf import OmegaConf
>>> OmegaConf.register_new_resolver("eval", eval)

Now, define a config and perform some arithmetic using the eval resolver:

>>> yaml_data = """
... ten_squared: ${eval:'10 ** 2'}
... """
>>> cfg = OmegaConf.create(yaml_data)
>>> assert cfg.ten_squared == 100

You can use nested interpolation to perform computation that involves other values from your config:

>>> yaml_data = """
... side_1: 5
... side_2: 6
... rectangle_area: ${eval:'${side_1} * ${side_2}'}
... """
>>> cfg = OmegaConf.create(yaml_data)
>>> assert cfg.rectangle_area == 30

To pass string data to eval, you’ll need to use a nested pair of quotes:

>>> yaml_data = """
... cow_say: moo
... three_cows: ${eval:'3 * "${cow_say}"'}
... """
>>> cfg = OmegaConf.create(yaml_data)
>>> assert cfg.three_cows == "moomoomoo"

The double quotes around "${cow_say}" guarantee that eval will interpret "moo" as a string instead of as a variable moo. See Escaping in interpolation strings for more information.

For more complicated logic, you should consider defining a specialized resolver to encapsulate the computation, rather than relying on the general capabilities of eval. Follow the examples from the Custom resolvers docs.