Loading “formattble” strings from plain text files

Little Tricks
Python
Author

Stefan Behrens

Published

August 22, 2025

I was recently playing around with generating HTML or LaTeX files using Python. For that purpose, it’s often conventient to use “formattable” strings with placeholders (eg. {stuff:s}) as code templates that can be filled with content. Sometimes it’s also a good idea to outsource these templates as plain text in auxiliary files (e.g. .html or .tex files). I’m going to demonstrate to methods to do this.

Standard string formatting

Below I’ve put some placeholder of the form {stuff:s} in an HTML file.

# Load HTML file with placeholders and print
template = "./templates/test_format.html"
with open(template, "r") as file:
    html_template = file.read()
print("HTML with placeholders:")
print("-"*20)
print(html_template)
HTML with placeholders:
--------------------
<html>
<head>
    <title>{page_title:s}</title>
</head>
<body>
    <h1>{h1:s}</h1>
    <p>{text:s}</p>
</body>
</html>

Since the placeholders are now in a string, standard string formatting is available:

# Fill placeholders and print again
print("HTML after filling placeholders:")
print("-"*20)
html = html_template.format(
    page_title="Title",
    h1="Headline",
    text="This is some text."
)
print(html)
HTML after filling placeholders:
--------------------
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>Headline</h1>
    <p>This is some text.</p>
</body>
</html>

Template Stings

The same works with template strings using placeholders of the form $stuff. To make use of these, the Template class from the string library is needed.

# Import the `Template` class from the string library
from string import Template

# Load HTML file with placeholders and print
template = "./templates/test_Template.html"
with open(template, "r") as file:
    html_template = file.read()
print("HTML with placeholders:")
print("-"*20)
print(html_template)
HTML with placeholders:
--------------------
<html>
<head>
    <title>$page_title</title>
</head>
<body>
    <h1>$h1</h1>
    <p>$text</p>
</body>
</html>

The placeholder can be filled by creating a Template object from the string and then using the metho .substitute(...).

# Create "template string"
html_template = Template(html_template)

# Fill placeholders and print again
print("HTML after filling placeholders:")
print("-"*20)
html = html_template.substitute(
    page_title="Title",
    h1="Headline",
    text="This is some text."
)
print(html)
HTML after filling placeholders:
--------------------
<html>
<head>
    <title>Title</title>
</head>
<body>
    <h1>Headline</h1>
    <p>This is some text.</p>
</body>
</html>

A LaTeX example

Template strings are particularly useful when working with LaTeX code, which usually contains a lot of backslashes \ and curly braces {...}. The curly braces are particularly annoying.

Here’s a simple example, again, first with placeholders.

# Import the `Template` class from the string library
from string import Template

# Load LaTeX file with placeholders and print
template = "./templates/test_Template.tex"
with open(template, "r") as file:
    latex_template = file.read()
print("LaTeX with placeholders:")
print("-"*20)
print(latex_template)
LaTeX with placeholders:
--------------------
\documentclass{article}

\author{Author}
\title{Title}
\date{\today}

\begin{document}

\section{$SECTION}

$TEXT

\end{document}

And now with content:

# Create "template string"
latex_template = Template(latex_template)

# Fill placeholders and print again
print("LaTeX after filling placeholders:")
print("-"*20)
latex = latex_template.substitute(
    SECTION="Introduction",
    TEXT= "This is some text."
)
print(latex)
LaTeX after filling placeholders:
--------------------
\documentclass{article}

\author{Author}
\title{Title}
\date{\today}

\begin{document}

\section{Introduction}

This is some text.

\end{document}

Trouble with standard string formatting

Finally, here’s a quick demonstration that standard string formatting does not work in this example. The problem is that Python cannot distinguiing the actual placeholders {stuff:s} from the many other things wrapped in curly braces. Every pair {...} looks like a placeholder.

In the example below, the interpreter treats {article} as in \documentclass{article} is a placeholder with key "article" and reports a key error.

# Load LaTeX file with placeholders and print
template = "./templates/test_format.tex"
with open(template, "r") as file:
    latex_template = file.read()
print("LaTeX with placeholders:")
print("-"*20)
print(latex_template)
print("\n")

# Fill placeholders and print again
print("LaTeX after filling placeholders:")
print("-"*20)
latex = latex_template.format(
    SECTION="Introduction",
    TEXT= "This is some text."
)
print(latex)
LaTeX with placeholders:
--------------------
\documentclass{article}

\author{Author}
\title{Title}
\date{\today}

\begin{document}

\section{{SECTION:s}}

{TEXT:s}

\end{document}


LaTeX after filling placeholders:
--------------------
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_8280\2517583926.py in <cell line: 0>()
     11 print("LaTeX after filling placeholders:")
     12 print("-"*20)
---> 13 latex = latex_template.format(
     14     SECTION="Introduction",
     15     TEXT= "This is some text."

KeyError: 'article'