Python Releases

Python 3.14 t-strings: build templates you can sanitize before rendering

Python 3.14 t-strings: build templates you can sanitize before rendering I have seen teams ship XSS bugs because someone “just used an f-string” in the wrong place. Python 3.14 template string literals (t-strings) help because they produce a Template you can inspect and sanitize before you turn it into a plain str, but only if […]

Jack Pauley December 10, 2025 6 min read

Python 3.14 t-strings: build templates you can sanitize before rendering

I have seen teams ship XSS bugs because someone “just used an f-string” in the wrong place.

Python 3.14 template string literals (t-strings) help because they produce a Template you can inspect and sanitize before you turn it into a plain str, but only if you actually run a renderer pipeline.

What t-strings are (and what they are not)

t-strings look like f-strings, but they do not immediately render.

You write t”Hello {user}” and get a string.templatelib.Template object that contains static text segments plus Interpolation objects, so you can escape, validate, or bind parameters before you output anything.

  • They do not make output “safe” by default: you must still escape HTML, bind SQL params, and apply formatting rules in your renderer.
  • They do not behave exactly like f-strings: conversions and format specs live on the interpolation object. Your renderer decides what to do with them.
  • They are not drop-in strings: lots of APIs expect str, so render at the boundary and pass strings downstream.

Setup: confirm you are on Python 3.14.2+

Check your runtime first.

Run python –version and make sure you are on Python 3.14.2 or newer, then import string.templatelib from the standard library.

Create a t-string, then inspect its parts

🔔 Never Miss a Breaking Change

Get weekly release intelligence — breaking changes, security patches, and upgrade guides before they break your build.

✅ You're in! Check your inbox for confirmation.

This bit surprised me the first time.

If you print a t-string, you do not get the final message. You get a structured object you can iterate, and each part will either be a plain string segment or an interpolation you must handle.

  • Create: t”Hello {user}” returns a Template, not str.
  • Inspect: iterate the Template and branch on Interpolation vs static text.
  • Important caveat: iteration skips empty string segments in the official API, so if you need exact segment layout, prefer the Template’s dedicated accessors (check the docs for the names on your exact 3.14.x build).

A minimal safe HTML renderer (the example you will actually reuse)

So.

Here’s the pattern that keeps you out of trouble: treat every interpolation as hostile until you escape it for the output context. I default to HTML-escaping because it is the place I see people get hurt most often.

Renderer contract: static text passes through, interpolation values get coerced to string, then escaped, then concatenated.

  • Input: Template plus a dict of values (the context).
  • Escape rule: HTML-escape every interpolated value unless you intentionally mark it safe.
  • Output: plain str you can hand to Flask/Django/your HTTP client.

If you skip the renderer and call str() on random objects mid-template, you did not buy safety. You bought a new way to make a mess.

Common failure modes (I keep seeing these)

It will break at first.

That’s fine. Most breakages come from confusing “template” with “string,” or from trying to use t-strings as a universal replacement for Jinja2-style templates.

  • You expected a str but got a Template: render explicitly at your module boundary. Do not let Template objects leak into libraries that only accept strings.
  • Your interpolations contain None, ints, or objects: coerce in one place (the renderer). Decide whether you want str(value), repr(value), or strict typing that raises.
  • You tried to use it for SQL: do not build SQL strings by concatenation. Use t-strings to build a structured representation, then bind parameters in your DB driver.
  • You benchmarked and saw a slowdown: profile first, then cache compiled templates or memoize expensive escaping functions. Do not guess.

When I would not use t-strings

Sometimes you should just not.

If you need template inheritance, loops, conditionals, i18n blocks, or designers editing templates, use a real template engine. I do not trust “we’ll keep it simple” as a long-term plan.

  • Complex HTML pages: use Jinja2/Django templates. Keep t-strings for small fragments where you want strict control.
  • Ultra-hot paths: measure before you convert everything. You can keep f-strings for internal, non-user-facing strings.
  • Mixed-version libraries: if you must support Python 3.13 and 3.14, gate the feature or provide a fallback path.

What to do next

Pick one risky string.

Find the place where user input enters HTML or logs, replace that one f-string with a t-string, and write a unit test that passes <script>alert(1)</script> as input and asserts the output escaped it. Other stuff in this release: dependency bumps, some image updates, the usual.

Keep Reading

Frequently Asked Questions

What are t-strings in Python 3.14? Template string literals (t-strings) are a new feature in Python 3.14 that look like f-strings but produce a Template object instead of a plain string. You write t"Hello {user}" and get a structured object you can inspect, sanitize, and render on your own terms. They live in the string.templatelib module.

Are t-strings a drop-in replacement for f-strings? No. T-strings produce a Template object, not a str. Most APIs that expect strings will break if you pass a Template directly. You need to run a renderer that converts the Template to a string after applying your escaping or sanitization logic. Think of them as f-strings with a mandatory processing step.

Do t-strings automatically prevent XSS or SQL injection? No. T-strings give you the opportunity to sanitize by separating static text from interpolated values, but they do not escape anything by default. You must write or use a renderer that handles HTML escaping, SQL parameter binding, or whatever your output context requires. The safety comes from your pipeline, not from the syntax itself.

What Python version do I need for t-strings? You need Python 3.14.0 or newer. The recommended minimum is Python 3.14.2, which fixes several crash regressions in the 3.14 line. Run python --version to check, then import string.templatelib to verify the module is available.