Monthly Archives: August 2018

Python with Jinja2 and YAML

Introduction

In this post we’ll see how to work with Jinja2 and YAML in your Python projects, to easily create and modify templates based on a YAML template. Essentially, we will use the configuration in the YAML file to replace the placeholders in the Jinja 2 template file.

Jinja2 is widely used, examples include Ansible and also Flask for instance. It’s an easy-to-use templating engine and definitely worth checking out.

Creating a template

To start using Jinja2, we first need a template. Let’s create a very basic template:

Hello {{ name }}!
Date is {{ date }}!

We will store this template in a ‘templates’ folder under the root directory of our Python project.

Creating a YAML file

As we want to use YAML to replace the curly brackets with the real data, we also need to prepare such YAML file.

name: "Hello World"
date: "31st May 2019"

Reading from CLI

We want to use the CLI to provide the required information. Ideally we will perform the conversion using the following syntax:

python3 main.py  

In Python, this would correspond to something like below:

if (len(sys.argv) == 3):
    j2_file = sys.argv[1]
    yaml_file = sys.argv[2]
else:
    print("   ######################################################\n")
    print("   Syntax is:\n")
    print("   python3 test.py template.j2 yaml_file.yml\n")
    print("   ######################################################\n")
    quit()

j2_file now contains the name of the jinja2 template while yaml_file contains the name of our yml file

The core part

First, we need to create an environment object. Then we use that environment to load the file itself. The FileSystemLoader specifies the folder where we find out templates, in our case we created a specific folder to hold the templates and called it ‘templates’. To load the template, we use the ‘get_template’ function. We now have a template object which allows us to render it in a later phase.

from jinja2 import Environment
from jinja2 import FileSystemLoader

j2_env = Environment(loader=FileSystemLoader('templates'), trim_blocks=True)
template = j2_env.get_template(j2_file)

Next, we also need to load our YAML file into an object. Note that ‘yaml_file’ contains the name of our yaml file.

f = open("./%s" % yaml_file)
data = f.read()
f.close()

yaml_data = yaml.load(data, Loader=yaml.FullLoader)

We now have an object ‘yaml_data’ which contains the following {‘name’: ‘Wim’, ‘date’: ’31st May 2019′}. In other words, it’s now a Python dictionary which we can use for the rendering. This is very straightforward:

rendered_file = template.render(yaml_data)

We use the Jinja2 template object and essentially replace the curly brackets with the dictionary data.

Full code

Below is the complete example:

from jinja2 import Environment
from jinja2 import FileSystemLoader
import re
import sys
import yaml
import datetime


if (len(sys.argv) == 3):
    j2_file = sys.argv[1]
    yaml_file = sys.argv[2]
else:
    print("   ######################################################\n")
    print("   Syntax is:\n")
    print("   python3 test.py template.j2 yaml_file.yml\n")
    print("   ######################################################\n")
    quit()


j2_env = Environment(loader=FileSystemLoader('templates'), trim_blocks=True)
template = j2_env.get_template(j2_file)

f = open("./%s" % yaml_file)
data = f.read()
f.close()
yaml_data = yaml.load(data, Loader=yaml.FullLoader)

rendered_file = template.render(yaml_data)
print(rendered_file)