---
title: "Python 3.14: Template Strings na Prática"
url: "https://python.dev.br/blog/python-3-14-template-strings/"
markdown_url: "https://python.dev.br/blog/python-3-14-template-strings.MD"
description: "Veja como usar template strings do Python 3.14 com exemplos reais, diferenças para f-strings e casos de uso em logs, HTML e DSLs."
date: "2026-04-10"
author: "Equipe python.dev.br"
---

# Python 3.14: Template Strings na Prática

Veja como usar template strings do Python 3.14 com exemplos reais, diferenças para f-strings e casos de uso em logs, HTML e DSLs.


O Python 3.14 traz uma novidade que chama atenção de quem acompanha a evolução da linguagem: as **template strings**, definidas na **PEP 750**. À primeira vista, elas parecem só mais uma variação das famosas f-strings. Mas a proposta é diferente: em vez de gerar imediatamente uma `str`, uma template string preserva a estrutura da interpolação para que seu código possa inspecionar, transformar ou serializar cada parte de forma controlada.

Na prática, isso abre espaço para bibliotecas de **HTML seguro**, **logging estruturado**, **DSLs**, geração de consultas e outros fluxos em que você quer manter separadas as partes estáticas do texto e os valores interpolados. Para quem já usa Python em automação, backend ou ferramentas internas, vale entender desde já como esse recurso funciona.

Neste artigo, vamos ver o que são template strings, como elas se diferenciam de f-strings, quais casos de uso fazem sentido e como experimentar a sintaxe do Python 3.14 com exemplos práticos.

## O que muda com template strings?

Com uma f-string tradicional, o Python avalia as expressões e produz uma string final:

```python
nome = "Diego"
mensagem = f"Olá, {nome}!"
print(mensagem)  # Olá, Diego!
print(type(mensagem))  # <class 'str'>
```

Com uma **template string**, usando o prefixo `t`, o resultado deixa de ser uma `str` simples. O Python cria um objeto de template que mantém as partes literais e as interpolações separadas:

```python
nome = "Diego"
template = t"Olá, {nome}!"

print(type(template))
# <class 'string.templatelib.Template'>
```

Segundo a PEP 750, essa estrutura foi criada para **custom string processing**. Ou seja: a linguagem passa a oferecer uma forma nativa de capturar uma string interpolada sem necessariamente convertê-la para texto final naquele momento.

Esse detalhe parece pequeno, mas muda bastante o jogo. Em vez de perder contexto logo na interpolação, você pode aplicar regras próprias de renderização, escape, validação e serialização depois.

## Template string vs f-string

A melhor forma de entender é comparar os dois recursos lado a lado:

| Recurso | f-string | template string |
|---------|----------|-----------------|
| Prefixo | `f"..."` | `t"..."` |
| Resultado | `str` | `Template` |
| Interpolação | Avalia e concatena | Avalia e preserva estrutura |
| Casos de uso | Texto final | Processamento customizado |
| Ideal para | Mensagens, labels, logs simples | HTML seguro, DSLs, logging estruturado |

A semelhança sintática é proposital. Você continua escrevendo expressões entre chaves, podendo usar conversões como `!r`, formatação como `:.2f` e até a sintaxe de debug `=`. A diferença é o que acontece **depois** da avaliação.

## Inspecionando as partes do template

Um template pode ser percorrido para acessar segmentos literais e interpolações. Isso é o que permite criar processadores reutilizáveis:

```python
from string.templatelib import Interpolation

produto = "Notebook"
preco = 4299.90
template = t"Produto: {produto} | Preço: R$ {preco:.2f}"

for parte in template:
    if isinstance(parte, Interpolation):
        print("Expressão:", parte.expression)
        print("Valor:", parte.value)
        print("Conversão:", parte.conversion)
        print("Format spec:", parte.format_spec)
    else:
        print("Texto literal:", parte)
```

Esse tipo de introspecção não existe com f-strings comuns. Quando você usa `f"..."`, o Python já devolve o texto pronto. Já na template string, cada interpolação é representada como um objeto com metadados úteis.

Isso lembra um pouco como frameworks modernos tratam **ASTs**, consultas estruturadas ou builders de HTML. A vantagem é que agora o próprio Python fornece uma sintaxe elegante para capturar esse material.

## Exemplo prático: renderização segura para HTML

Um caso de uso clássico é escapar valores interpolados para evitar problemas de HTML injection. Em vez de concatenar strings manualmente, podemos processar o template:

```python
from html import escape
from string.templatelib import Interpolation


def render_html_seguro(template) -> str:
    partes = []

    for parte in template:
        if isinstance(parte, Interpolation):
            partes.append(escape(str(parte.value)))
        else:
            partes.append(parte)

    return "".join(partes)


usuario = "<script>alert('xss')</script>"
pagina = t"<p>Bem-vindo, {usuario}!</p>"
html_final = render_html_seguro(pagina)

print(html_final)
# <p>Bem-vindo, &lt;script&gt;alert(&#x27;xss&#x27;)&lt;/script&gt;!</p>
```

Se você fizesse isso com f-strings puras, teria de lembrar de escapar cada valor antes da interpolação. Com template strings, a regra fica centralizada em uma função. Esse padrão pode ser útil em ferramentas internas, mini motores de template e integrações web. Se você trabalha com APIs e aplicações web, vale revisar também nosso conteúdo sobre [FastAPI](/blog/apis-rest-com-fastapi/) e [segurança em aplicações Python](/blog/seguranca-em-aplicacoes-python/).

## Exemplo prático: logging estruturado

Outro cenário interessante é logging. Em muitos sistemas, queremos guardar não só a mensagem renderizada, mas também os valores originais para indexação, busca ou observabilidade.

```python
from string.templatelib import Interpolation


def log_estruturado(template) -> dict:
    mensagem = []
    campos = {}

    for indice, parte in enumerate(template):
        if isinstance(parte, Interpolation):
            chave = parte.expression or f"campo_{indice}"
            campos[chave] = parte.value
            mensagem.append(f"{{{chave}}}")
        else:
            mensagem.append(parte)

    return {
        "message_template": "".join(mensagem),
        "fields": campos,
    }


usuario_id = 42
acao = "checkout"
resultado = log_estruturado(t"Usuário {usuario_id} executou {acao}")
print(resultado)
```

Saída esperada:

```python
{
    'message_template': 'Usuário {usuario_id} executou {acao}',
    'fields': {
        'usuario_id': 42,
        'acao': 'checkout'
    }
}
```

Esse modelo conversa bem com pipelines de observabilidade e sistemas de métricas. Para quem usa Python em backend e automação, pode ser uma alternativa elegante a montar dicionários e mensagens em separado. Se você gosta desse tipo de arquitetura, aproveite para ler também nosso artigo sobre [logging em Python](/blog/logging-em-python/).

## Exemplo prático: DSL simples para consultas

Template strings também podem servir como base para uma DSL controlada. A ideia não é montar SQL cru sem cuidado, mas demonstrar como separar estrutura e parâmetros:

```python
from string.templatelib import Interpolation


def compilar_consulta(template):
    sql = []
    parametros = []

    for parte in template:
        if isinstance(parte, Interpolation):
            sql.append("%s")
            parametros.append(parte.value)
        else:
            sql.append(parte)

    return "".join(sql), parametros


status = "ativo"
limite = 10
consulta, params = compilar_consulta(
    t"SELECT * FROM clientes WHERE status = {status} LIMIT {limite}"
)

print(consulta)
print(params)
```

Resultado:

```python
SELECT * FROM clientes WHERE status = %s LIMIT %s
['ativo', 10]
```

Esse padrão ajuda a reforçar a separação entre comando e parâmetros. Em aplicações reais, você continuaria usando o driver ou ORM adequado, como mostramos em conteúdos sobre [PostgreSQL com Python](/blog/python-e-postgresql/) e [MongoDB com Python](/blog/python-e-mongodb/).

## O que continua igual em relação às f-strings?

Apesar do novo propósito, as template strings reaproveitam boa parte da ergonomia das f-strings. Você ainda pode usar:

- expressões Python entre chaves;
- conversões como `!r` e `!s`;
- format spec como `:.2f`;
- formas raw, como `rt"..."` e `tr"..."`;
- sintaxe de debug com `=`.

Exemplo:

```python
valor = 123.456
template = t"Valor formatado: {valor:.1f}"
```

A interpolação continua sendo avaliada da esquerda para a direita, assim como ocorre com f-strings. Ou seja, template strings **não** são avaliação preguiçosa das expressões; o que elas adiam é a transformação no texto final.

## Limitações e cuidados

Como o recurso ainda é novo no ecossistema, alguns cuidados são importantes:

1. **Bibliotecas ainda estão se adaptando**: não espere integração imediata com todos os frameworks.
2. **Não é substituição universal de f-strings**: para mensagens simples, f-strings continuam mais diretas.
3. **Exige Python 3.14**: se seu ambiente de produção ainda roda 3.12 ou 3.13, o recurso serve mais para exploração e planejamento.
4. **Não existe conversão padrão única para string**: o ponto da feature é justamente deixar a renderização sob controle do desenvolvedor.

Por isso, o melhor jeito de pensar nesse recurso é como uma ferramenta de **baixo nível e alto poder**, especialmente útil para bibliotecas e camadas de infraestrutura.

## Vale a pena aprender agora?

Sim, principalmente se você gosta de acompanhar recursos que podem influenciar o design de bibliotecas Python nos próximos anos. Template strings têm potencial para aparecer em soluções de:

- sanitização de conteúdo;
- renderização segura de HTML e Markdown;
- logging estruturado;
- geração de consultas e comandos;
- DSLs internas;
- ferramentas de automação com saída formatada.

Mesmo que você não use no dia a dia imediatamente, entender a ideia ajuda a enxergar para onde o Python está indo: menos hacks com concatenação, mais estruturas explícitas e reutilizáveis.

## Conclusão

As template strings do Python 3.14 mostram que a linguagem continua evoluindo não apenas em performance, mas também em **expressividade para bibliotecas e infraestrutura**. A sintaxe familiar reduz a curva de aprendizado, enquanto o retorno em forma de `Template` cria novas possibilidades para processar texto de maneira mais segura e estruturada.

Para quem trabalha com backend, automação e ferramentas internas, esse é o tipo de novidade que pode parecer nichada no começo, mas ganhar tração rapidamente quando surgirem bibliotecas explorando bem a feature.

Se você quer acompanhar outras mudanças recentes do ecossistema, veja também nossos artigos sobre [Python 3.13 e o modo free-threaded](/blog/python-3-13-free-threaded-sem-gil/), [tipagem estática com mypy](/blog/tipagem-estatica-python-mypy/) e [boas práticas em Python para 2026](/blog/boas-praticas-python-2026/).

Curiosidade: <a href="https://golang.com.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'golang.com.br' })">Go já tem `text/template` e `html/template`</a> como parte da stdlib, com escape automático de HTML — a mesma filosofia de segurança que as template strings do Python 3.14 trazem agora.
