Pystpl - A Simple Python Template Parser
Jun, 2017
For a different project I needed a template parser in python. Of course, there exists already a large amount of template engines. However, out of interest, I decided to write my own template engine suited for my needs. The library itself consists of a single file and contains only a few hundred lines of code. The library has the following features:
- Variable tag markers (default "[[" and "]]")
- Placeholders for variables including arbitrarily nested dicts or class properties
- Strings can be marked to be translated by gettext
- Loops including loop count variable
- Conditional expressions, if and else
- Option to define an escaping method for variables
- Expressive error messages including line/character if template contains errors
Usage
The usage is straight forward. Consider the following example template text
text = """
Lorem ipsum dolor sit [[var1]] amet, consectetur adipisicing [[foo.bar]] elit.
[[FOR i,item1 IN list1]][[FOR j,item2 IN list2]]
[[i]],[[j]]: [[item1]], [[item2]]
[[ENDFOR]][[ENDFOR]]
[[FOR item IN list1]]
[[item]]
[[ENDFOR]]
[[IF var2 == "lalilu"]]
var2 is lalilu
[[ELSE]]
var2 is not lalilu
[[ENDIF]]
[[IF var3 > 103]]
var3 > 103
[[ENDIF]]
[[IF var3 < 103]]
var3 < 103
[[ENDIF]]
[[IF var3 <= 103]]
var3 <= 103
[[ENDIF]]
[[IF var3 <= 103]]
var3 <= 103
[[ENDIF]]
[[IF var3 != 103]]
var3 != 103
[[ENDIF]]
[[IF var1 == var2]]
var1 == var2
[[ENDIF]]
"""
Variables are marked as [[variablename]]
.
The loop and condition syntax is the same as in normal python
also marked with opening and closing characters like [[SOME EXPRESSION]]
.
For further syntax information see the README.
To evaluate the example consider the following code
import pystpl
# example data
data = {
"var1" : "this is a test",
"var2" : "lalilu",
"var3" : 10,
"foo" : {"bar" : 123},
"list1" : [44,56,11],
"list2" : ["blub", "haha"]
}
# define an example quote method
def quote(text):
return text.replace("a", "AA")
try:
# parse template
tpl = pystpl.Tpl(text)
# evaluate template and fill placeholders with data
print(tpl.substitute(data, quote))
except pystpl.TplError as e:
print(e)
The output is
Lorem ipsum dolor sit this is AA test amet, consectetur adipisicing 123 elit. 1,1: 44, blub 1,2: 44, hAAhAA 2,1: 56, blub 2,2: 56, hAAhAA 3,1: 11, blub 3,2: 11, hAAhAA 44 56 11 var2 is lalilu var3 < 103 var3 <= 103 var3 <= 103 var3 != 103
Benchmark
To check how my implementation performs considering the execution time in comparison with other template engines I used the benchsimple benchmark, which I found on the website www.simple-is-better.org. The configuration file for the benchmark and the result can be found here. Running the benchmark in comparison with other engines gives the following result:
pystpl 0.0.1 ------- import: 10.4709 ms complete: 3.7436 ms parse only: 0.4104 ms render only: 3.2643 ms Cheetah ?.? ------- import: 80.0281 ms complete: 2.2945 ms parse only: 0.0251 ms render only: 2.2269 ms mako 1.0.6 ------- import: 92.7191 ms complete: 5.8826 ms parse only: 5.6144 ms render only: 0.2084 ms jinja2 2.9.6 ------- import: 68.5041 ms complete: 7.1358 ms parse only: 6.8045 ms render only: 0.3144 ms
Compared with other template engines, my implementation performs quite well.