Conditional Logic in YAML with Python (Custom Loading)
This tutorial will guide you through several methods to implement conditional logic in YAML using Python.
We’ll use template engines like Jinja2, custom YAML tags, and combine YAML with Python classes.
Using Jinja2 with YAML for Conditional Logic
You can use Jinja2 to introduce conditional statements within your YAML files which allows dynamic configuration based on variables.
import yaml
from jinja2 import Template
yaml_template = """
user: {{ name }}
role: {% if admin %}admin{% else %}user{% endif %}
permissions:
- read
{% if admin %}
- write
- delete
{% endif %}
"""
template = Template(yaml_template)
rendered = template.render(name="Mona", admin=True)
config = yaml.safe_load(rendered)
print(config)
Output:
{'user': 'Mona', 'role': 'admin', 'permissions': ['read', 'write', 'delete']}
Here, Jinja2 processes the YAML template to include additional permissions if the user is an admin.
Using Custom Tags and YAML Constructors
Creating custom tags in YAML allows for more conditional processing when combined with Python constructors.
import yaml
class DeferredIf:
def __init__(self, condition, true_val, false_val):
self.condition = condition
self.true_val = true_val
self.false_val = false_val
def if_constructor(loader, node):
value = loader.construct_sequence(node)
if len(value) != 3:
raise yaml.constructor.ConstructorError(
None, None,
"!if tag requires exactly three arguments",
node.start_mark)
return DeferredIf(*value)
class CustomLoader(yaml.SafeLoader):
pass
CustomLoader.add_constructor('!if', if_constructor)
yaml_data = """
environment: production
debug_mode: !if [environment == 'production', false, true]
"""
config = yaml.load(yaml_data, Loader=CustomLoader)
for key, value in config.items():
if isinstance(value, DeferredIf):
condition = value.condition.replace('environment', f"config['environment']")
config[key] = value.true_val if eval(condition) else value.false_val
print(config)
Output:
{'environment': 'production', 'debug_mode': False}
This example defines a custom !if tag to conditionally set debug_mode based on the environment.
Combine YAML with Python Classes
Integrating Python classes with YAML allows you to manage conditional configurations through object-oriented programming.
import yaml
class Config:
def __init__(self, environment):
self.environment = environment
self.settings = self.load_settings()
def load_settings(self):
with open('config.yaml') as f:
data = yaml.safe_load(f)
env_config = data.get(self.environment, {})
return env_config
config = Config(environment='development')
print(config.settings)
The config.yaml file:
development:
debug: true
database:
host: dev.db.local
port: 5432
production:
debug: false
database:
host: prod.db.server
port: 5432
Output:
{'debug': True, 'database': {'host': 'dev.db.local', 'port': 5432}}
By using a Python class to load configurations based on the environment, you allow conditional logic that adjusts settings dynamically.
Mokhtar is the founder of LikeGeeks.com. He is a seasoned technologist and accomplished author, with expertise in Linux system administration and Python development. Since 2010, Mokhtar has built an impressive career, transitioning from system administration to Python development in 2015. His work spans large corporations to freelance clients around the globe. Alongside his technical work, Mokhtar has authored some insightful books in his field. Known for his innovative solutions, meticulous attention to detail, and high-quality work, Mokhtar continually seeks new challenges within the dynamic field of technology.