Python Template Strings — Core Concepts
Python offers several string formatting approaches: f-strings, .format(), and %-formatting. But there’s a fourth option that serves a distinct purpose: the string.Template class.
What Template Strings Are
string.Template is a class in Python’s standard library that performs simple $-based substitution. It was introduced in PEP 292 as a deliberately less powerful formatting mechanism.
The key difference from other formatting options: Template strings cannot evaluate expressions. They can only replace named placeholders with values.
Basic Usage
A template uses $identifier or ${identifier} for placeholders:
from string import Template
t = Template("Hello, $name! You have $count new messages.")
result = t.substitute(name="Alice", count=5)
# "Hello, Alice! You have 5 new messages."
Use braces when the placeholder borders other text:
t = Template("${noun}ification process complete")
t.substitute(noun="class")
# "classification process complete"
substitute vs. safe_substitute
substitute() raises KeyError if a placeholder is missing. safe_substitute() leaves missing placeholders untouched:
t = Template("$greeting, $name!")
t.safe_substitute(greeting="Hi")
# "Hi, $name!" — $name left as-is instead of crashing
Use safe_substitute() when partial rendering is acceptable, such as multi-pass template processing.
The Security Angle
This is the primary reason Template strings exist. Consider the difference:
With f-strings or .format(), the person who writes the template string can embed arbitrary Python expressions:
# DANGEROUS if template comes from user input:
user_template = "{person.__class__.__mro__}"
user_template.format(person=some_object)
# Exposes internal class hierarchy
With Template strings, there is no expression evaluation. $person.__class__ is not valid Template syntax — it just looks for a variable literally named person.
Rule of thumb: If you control the template, use f-strings. If the template comes from outside (users, config files, databases), use string.Template.
How It Works
Templates use a simple regex under the hood to find placeholders. The default pattern matches:
| Pattern | Example | Behavior |
|---|---|---|
$identifier | $name | Named substitution |
${identifier} | ${name} | Same, with explicit braces |
$$ | $$ | Literal dollar sign |
The identifier must be a valid Python identifier (letters, digits, underscores, cannot start with a digit).
Customizing Templates
You can subclass Template to change the delimiter or pattern:
class PercentTemplate(Template):
delimiter = "%"
t = PercentTemplate("Hello, %name!")
t.substitute(name="Bob")
# "Hello, Bob!"
This is useful when dollar signs appear frequently in your text (like financial documents) and you need a different marker.
When to Use Each Formatting Method
| Method | Speed | Power | Safety | Best for |
|---|---|---|---|---|
| f-strings | Fastest | Full expressions | Trusted code only | Developer-written strings |
.format() | Fast | Attribute access, indexing | Moderate risk | Dynamic format strings |
%-formatting | Fast | Limited | Lower risk | Legacy code |
Template | Slowest | Substitution only | Safest | User-supplied templates |
Common Misconception
“Template strings are outdated and never needed.” They serve a specific security niche that no other Python formatting method covers. Any time a template comes from untrusted input — user-generated email templates, plugin configurations, localization files — Template strings are the correct choice.
One Thing to Remember
Template strings exist for one reason: safe substitution when the template source isn’t trusted. They deliberately sacrifice power for security, and that tradeoff is their strength.
See Also
- Python Csv Processing Learn how Python reads and writes spreadsheet-style CSV files — the universal language of data tables.
- Python Json Handling See how Python talks to the rest of the internet using JSON — the universal language apps use to share information.
- Python Toml Configuration Discover TOML — the config file format Python chose for its own projects, designed to be obvious and impossible to mess up.
- Ci Cd Why big apps can ship updates every day without turning your phone into a glitchy mess — CI/CD is the behind-the-scenes quality gate and delivery truck.
- Containerization Why does software that works on your computer break on everyone else's? Containers fix that — and they're why Netflix can deploy 100 updates a day without the site going down.