Fail on missing string.Template placeholders before shipping a report
To fail on missing string.Template placeholders before shipping a report, render with Template.substitute() rather than safe_substitute(). substitute() raises KeyError when note is absent, allowing the caller to stop the report path. In contrast, safe_substitute() leaves ${note} in the output, which can silently ship an unresolved marker.
The template also demonstrates two dollar-sign details. $$ produces one literal dollar, so $$${amount} renders as $12. The supplied note contains $later, but it is inserted as ordinary text; Template does not evaluate replacement text as another template pass. The assertion confirms that observed single-pass result. This is useful for describing Template behavior, but it is not HTML escaping, SQL parameterization, or general-purpose sanitization.
The example catches only the expected missing-key case and records the missing field name. In an application, decide whether the exception should reach the caller, be converted to a validation result, or be logged without exposing report data. Also validate the values’ meaning separately; strict placeholder completeness only says that a named mapping entry existed.
Python documents the different missing-placeholder behavior of substitute() and safe_substitute(), as well as $$ escaping. These APIs are longstanding in Python 3 and do not require a newer version.
AI assistance disclosure: this article was prepared with AI assistance and checked against the shown synthetic fixture.
Source: Python string.Template.
from string import Template
template = Template("Cost: $$${amount}; note: ${note}")
complete = {"amount": "12", "note": "Use $later literally"}
rendered = template.substitute(complete)
try:
template.substitute({"amount": "12"})
except KeyError as error:
missing_field = error.args[0]
else:
raise AssertionError("the incomplete mapping should fail")
safe_rendered = template.safe_substitute({"amount": "12"})
assert rendered == "Cost: $12; note: Use $later literally"
assert missing_field == "note"
assert safe_rendered == "Cost: $12; note: ${note}"
print("complete:", rendered)
print("substitute missing:", missing_field)
print("safe missing:", safe_rendered)
complete: Cost: $12; note: Use $later literally
substitute missing: note
safe missing: Cost: $12; note: ${note}