Free Python reference · JavaScript timeline
Python 3.14: Separate interpolation from rendering
Template strings retain values for processing; annotations defer evaluation; native concurrency options continue evolving.
Released · Editorial review October 25, 2026
Introduced in Python 3.14 · Syntax
Template strings with a t prefix
A t-string resembles an f-string but produces a Template object rather than a finished string. It retains static text and interpolation values so a processor can choose how to handle them.
This separation is useful for custom formatting or context-aware processing. It is not automatic escaping: the code that consumes the template must implement the appropriate rules for its destination. In particular, creating a template does not by itself make HTML or SQL safe.
The example inspects the two pieces of static text and the interpolated value. The expression is evaluated when the template is created; later rendering choices belong to the consumer.
Worked example
Minimum Python 3.14 · Run locally
name = "Ada" message = t"Hello, {name}!" print(type(message).__name__) print(message.strings) print(message.interpolations[0].value)
Expected output
Template
('Hello, ', '!')
Ada
Example checked with CPython 3.14.8, CPython 3.15.0.
Common mistake
A Template is not a str. Do not send it to an API expecting a string without a deliberate rendering or processing step.
Try it yourself
Change name to text containing angle brackets. Explain why merely storing it in a template has not escaped it for HTML.
Read more: Python 3.14 release notes · PEP 750
Introduced in Python 3.14 · Language behavior
Annotations are evaluated when needed
By default, Python 3.14 defers evaluation of annotations instead of evaluating them immediately when a definition runs. Forward references can therefore name a class that will be defined later, provided it exists when an operation actually needs the value.
annotationlib offers tools for inspecting annotations in different formats. Asking for values can execute annotation expressions and still raise an error if a name is unresolved. Annotation inspection should therefore be treated as evaluation of code, not as reading inert labels.
This behavior differs from the earlier optional from __future__ import annotations, which stores string forms. The example intentionally has no future import and requests values after the class exists.
Worked example
Minimum Python 3.14 · Run locally
from annotationlib import get_annotations def identity(value: Later) -> Later: return value class Later: pass annotations = get_annotations(identity) print(annotations["value"] is Later) print(annotations["return"] is Later)
Expected output
True
True
Example checked with CPython 3.14.8, CPython 3.15.0.
Common mistake
Deferred does not mean never evaluated. Accessing value-form annotations before Later exists can still fail, and annotations still do not validate calls.
Try it yourself
Move get_annotations(identity) above the class definition. Predict the exception and explain the point at which the name is needed.
Read more: Python 3.14 release notes · PEP 649
Introduced in Python 3.14 · Standard library
Multiple interpreters through the standard library
concurrent.interpreters exposes separate Python interpreters within one native process. Each has its own interpreter state. This is different from creating ordinary threads that directly share the same Python objects.
Isolation changes the communication model: work and data must be sent using supported mechanisms. This is useful background for understanding InterpreterPoolExecutor, but it is not a replacement for designing data ownership and failure handling.
The example creates one interpreter, executes a small assertion in it, and closes it in a finally block. Run it in native CPython; browser WebAssembly environments do not provide the same capability.
Worked example
Minimum Python 3.14 · Run locally
from concurrent import interpreters worker = interpreters.create() try: worker.exec("assert 6 * 7 == 42") finally: worker.close() print("worker closed")
Expected output
worker closed
Example checked with CPython 3.14.8, CPython 3.15.0.
Common mistake
Separate interpreters do not automatically share your local variables or support every extension module. Close resources even when work raises an exception.
Try it yourself
Change the assertion so it fails. Confirm cleanup still happens, and describe what the caller needs to report.
Read more: Python 3.14 release notes · PEP 734
Introduced in Python 3.14 · Interpreter capability
Free-threading becomes supported
Python 3.14 advances free-threaded CPython from the experimental status introduced in 3.13 to a supported option. It remains a distinct build choice rather than a promise that every ordinary installation runs without a GIL.
Extension modules may need compatible builds, and shared mutable data still needs a synchronization design. A program being correct under a GIL-enabled interpreter is not sufficient evidence that it is safe with true parallel access.
The diagnostic below reports the current GIL state on CPython. Its output depends on the running build and loaded extensions. It illustrates an inspection step, not a performance benchmark or a browser capability.
Worked example
Minimum Python 3.14 · Run locally
import sys print(sys._is_gil_enabled())
Expected output
True
True is the result on the tested standard GIL-enabled CPython build. A free-threaded build may report False; that configuration is not benchmarked here.
Example checked with CPython 3.14.8, CPython 3.15.0.
Common mistake
Do not advertise free-threading as a feature of every Python 3.14 binary. Confirm the actual build and dependency support first.
Try it yourself
If the diagnostic prints False, identify one mutable object in your application that multiple threads could access and explain how ownership should work.
Read more: Python 3.14 release notes · PEP 779
Recap
Template strings retain values for processing; annotations defer evaluation; native concurrency options continue evolving. Prefer the clearest form that works on your project's supported Python versions.
Read the full Python 3.14 release notes →