Python string Template performs dollar-based placeholder substitution through the standard library’s string module. It is useful for simple messages and configuration text that do not need a full template engine. The class is intentionally small, which makes its limits easier to understand and test.
The most misleading name is safe_substitute(). Here, “safe” means the method tries to return a string despite certain missing or malformed placeholders. It does not mean the output is safe HTML, safe SQL, a safe shell command, or a complete message ready to publish.
Define the template’s purpose first
A plain-text notification and an HTML fragment require different output handling. A configuration file may have its own escaping rules. A command interface should usually preserve structured arguments instead of using text substitution to construct executable strings.
Choose Template when the intended grammar is simple placeholder replacement. If the workflow requires loops, nested objects, or context-sensitive HTML escaping, use a tool designed for those needs and review its security contract.
Keep template editing authority separate from value editing authority. A user allowed to choose a display name should not automatically be allowed to change the entire notification template. Text can influence user behavior even when it is never executed as code.
Python string Template uses dollar placeholders
The default syntax includes $name and ${name}. Braces help when a placeholder is adjacent to text that could otherwise become part of its identifier. $$ produces a literal dollar sign.
from string import Template
message = Template("Hello $name. Your plan costs $$${price}.")
rendered = message.substitute(name="Ayesha", price="12")
assert rendered == "Hello Ayesha. Your plan costs $12."
The example substitutes plain text. It makes no claim about HTML rendering, currency precision, or whether the price is an authorized offer. Those decisions belong to the surrounding application.
Values are inserted into the resulting string rather than evaluated as Python expressions. That is a useful simplicity property, but it does not prevent the next component from interpreting the output under another grammar.
Prefer strict substitution for final artifacts
substitute() raises a KeyError when a required placeholder is missing. Invalid placeholder syntax can raise a ValueError. These failures are helpful when a final message must be complete.
By contrast, safe_substitute() can leave an unresolved placeholder in the output. It can also tolerate malformed dollar syntax that strict substitution would reject. This behavior is useful for an intentional partial-editing workflow, but dangerous when callers mistake returned text for validated text.
Decide where partial rendering is permitted. A template preview may show unresolved values to an editor. A customer message or deployment configuration should normally pass a stricter completion check before it is sent or used.
Handle failures without logging private substitution values. An error report can identify the template revision and missing key while keeping account details or secrets out of broadly accessible logs.
Validate placeholders against an approved schema
On Python versions that support them, is_valid() checks whether the template contains invalid placeholders, and get_identifiers() lists valid identifiers. Confirm their availability in the runtime you deploy.
Use these helpers to compare a template’s requested fields with an approved set. Reject unknown placeholders before an editor saves a production template. Also verify that the supplied mapping contains every required field before final substitution.
Identifier discovery ignores invalid identifiers, so it is not a substitute for syntax validation. Run both checks where supported. A template with a malformed delimiter should not pass just because its remaining valid identifiers are allowed.
Supply a small plain mapping of approved values rather than exposing a large application context. Least-data rendering limits accidental disclosure and makes the template’s data dependency easier to review.
Escape for the destination, not for the placeholder
Template does not perform context-aware escaping. If the result enters HTML, escape values for the precise HTML context or use an appropriate autoescaping renderer. Text content, attributes, URLs, and scripts do not share one universal escaping rule.
Do not construct SQL by substituting user values into a query. Use parameterized database operations. Likewise, do not build a shell command with Template and assume dollar substitution made its arguments safe; use a structured subprocess interface and explicit authorization.
Even plain-text output can need controls. Newline characters may alter a log entry or header-like format. A value can also include misleading text, control characters, or an unexpected length. Apply the destination’s data validation and representation rules before rendering.
If an output later passes through another template engine, avoid accidental double interpretation. Inserted values containing placeholder-like text should remain data unless a deliberately reviewed second rendering stage is required.
Make default precedence visible
The API accepts a mapping and keyword arguments. When the same key appears in both, keyword arguments take precedence. This can be convenient for a small override but confusing when configuration is assembled from several layers.
Build one effective mapping before rendering where possible. Document which source wins and show the final non-sensitive values in a preview. Do not let a fallback silently replace an authorized value with a less trusted one.
Distinguish missing, empty, and null-like inputs. An empty display name may be invalid even though the key exists. Converting every value to a string can turn an absent value into the literal text “None,” which is usually not an acceptable customer message.
Test realistic templates and values
Include dollar signs, braced names next to suffixes, repeated placeholders, missing keys, empty values, and malformed delimiters. Add Unicode and multiline values if the interface permits them.
Test a value containing $other to confirm the intended single substitution stage. Include destination-sensitive characters and verify the complete rendering path, not only the output of Template in isolation.
For a final artifact, assert that the expected fields were rendered and that prohibited incomplete output cannot be sent. Avoid detecting every dollar sign as an unresolved placeholder because literal currency signs may be legitimate. Use validated template metadata instead of a crude final-string heuristic.
Keep fixtures for template revisions. A wording change that adds a new placeholder is a data-contract change and should fail tests until the caller supplies that field deliberately.
Frequently asked questions
Is safe_substitute a security feature?
It is an error-tolerant substitution method. It does not sanitize values or certify that the output is complete and safe for another interpreter.
Can Template replace an HTML template engine?
Only for carefully controlled simple uses with explicit escaping. It does not provide context-aware HTML autoescaping or a complete page-template workflow.
Should missing values always become empty strings?
No. Empty output can hide a broken contract. Choose defaults by field meaning and reject missing required information before publication.
Practical takeaway
Use simple placeholders with a small approved mapping. Validate template syntax, prefer strict substitution for final output, and escape according to the destination. A successfully returned string is not automatically a successfully completed artifact.
Documentation and related reading
Check the official documentation for the exact behavior of your deployed version. For complementary implementation guidance, read the context-aware XSS prevention guide.