Is there a native templating system for plain text files in Python?
I am looking for either technique or templating system for Python for formatting output to simple text. What I require is that it will be able to iterate through multiple lists or dicts. It would be nice if I would be able to define template into separate file (like output.templ) instead of hardcoding it into source code.
As simple example what I want to achieve, we have variables title
, subtitle
and list
title = 'foo'
subtitle = 'bar'
list = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', '开发者_开发技巧Sunday']
And running throught a template, output would look like this:
Foo
Bar
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday
How to do this? Thank you.
You can use the standard library string an its Template class.
Having a file foo.txt
:
$title
$subtitle
$list
And the processing of the file (example.py
):
from string import Template
d = {
'title': 'This is the title',
'subtitle': 'And this is the subtitle',
'list': '\n'.join(['first', 'second', 'third'])
}
with open('foo.txt', 'r') as f:
src = Template(f.read())
result = src.substitute(d)
print(result)
Then run it:
$ python example.py
This is the title
And this is the subtitle
first
second
third
There are quite a number of template engines for python: Jinja, Cheetah, Genshi etc. You won't make a mistake with any of them.
If your prefer to use something shipped with the standard library, take a look at the format string syntax. By default it is not able to format lists like in your output example, but you can handle this with a custom Formatter which overrides the convert_field
method.
Supposed your custom formatter cf
uses the conversion code l
to format lists, this should produce your given example output:
cf.format("{title}\n{subtitle}\n\n{list!l}", title=title, subtitle=sibtitle, list=list)
Alternatively you could preformat your list using "\n".join(list)
and then pass this to your normal template string.
if you want arbitrary prefixes/suffixes to identify your variables, you can simply use re.sub
with a lambda expression:
from pathlib import Path
import re
def tpl(fn:Path, v:dict[str,str]) -> str:
text = fn.with_suffix('.html').read_text()
return re.sub("(<!-- (.+?) -->)", lambda m: v[m[2].lower()], text)
html = tpl(Path(__file__), {
'title' : 't',
'body' : 'b'
})
精彩评论