string.Template: templates simples e seguros

Publicado em: 09/09/2026
Tempo de leitura: 6 minutos
Desenvolvedor criando modelos de texto com string.Template no Python

O string.Template é uma alternativa simples e segura para criar textos com campos substituíveis no Python. Em vez de misturar lógica complexa dentro de uma string, você define marcadores como $nome e fornece os valores separadamente. Esse modelo é especialmente útil em mensagens, arquivos de configuração, modelos de e-mail, notificações, relatórios e conteúdos editáveis por pessoas que não precisam conhecer a sintaxe completa das f-strings.

O que é string.Template

A classe Template pertence ao módulo padrão string. Ela trabalha com placeholders iniciados por cifrão. Um marcador pode ser escrito como $nome ou ${nome}. A segunda forma é útil quando o nome aparece junto de outros caracteres. O uso básico começa com from string import Template, seguido da criação do modelo e da chamada de substitute.

from string import Template
modelo = Template("Olá, $nome! Seu plano é ${plano}Premium.")
texto = modelo.substitute(nome="Ana", plano="Python ")
print(texto)

O resultado é um texto final sem precisar concatenar valores manualmente. Isso reduz erros de pontuação e deixa o modelo mais legível. Para revisar conceitos básicos de texto, veja Strings em Python e f-strings no Python.

substitute e safe_substitute

O método substitute exige que todos os campos estejam disponíveis. Se faltar uma chave, ele gera KeyError. Esse comportamento é ótimo quando o preenchimento incompleto representa um erro que deve ser descoberto imediatamente.

modelo = Template("Pedido $codigo para $cliente")
modelo.substitute(codigo="A-10")  # KeyError: cliente

safe_substitute mantém o placeholder original quando o valor não existe. Ele é útil em editores de modelos, pré-visualizações e fluxos nos quais os dados chegam em etapas.

rascunho = modelo.safe_substitute(codigo="A-10")
print(rascunho)  # Pedido A-10 para $cliente

Apesar do nome, safe_substitute não transforma conteúdo não confiável em conteúdo seguro para HTML, SQL ou shell. Ele apenas evita a exceção por chave ausente. Para tratamento de falhas, consulte Try Except no Python.

Quando usar Template em vez de f-string

F-strings são ideais quando o desenvolvedor controla o código e quer expressões, formatação numérica ou chamadas de função. Template é melhor quando o texto pode ser editado fora do código, por exemplo em um arquivo, banco de dados ou painel administrativo. Ele oferece uma linguagem de modelo deliberadamente limitada. Essa limitação é uma vantagem: quem edita o texto não consegue executar expressões Python dentro do marcador.

Em uma f-string, expressões são avaliadas no momento da execução. Em um Template, os marcadores são apenas nomes. Isso separa dados e apresentação. O modelo pode ser armazenado, revisado, traduzido e reutilizado. Para projetos com arquivos externos, veja como ler arquivos TXT e JSON no Python.

Preenchendo com dicionários

O método aceita um mapping como primeiro argumento. Isso facilita integrar dados vindos de APIs, formulários ou arquivos JSON.

dados = {"produto": "Curso de Python", "valor": "R$ 99"}
modelo = Template("$produto disponível por $valor")
print(modelo.substitute(dados))

Também é possível combinar mapping e argumentos nomeados. Os argumentos nomeados têm prioridade. Essa técnica permite definir valores padrão e substituir apenas campos específicos em determinado contexto.

padrao = {"empresa": "Academify", "canal": "site"}
texto = Template("$empresa atende pelo $canal")
print(texto.substitute(padrao, canal="WhatsApp"))

Validando campos antes de substituir

Em sistemas maiores, convém descobrir quais placeholders existem no modelo antes do preenchimento. Versões recentes do Python oferecem métodos como is_valid() e get_identifiers(). O primeiro informa se a sintaxe do modelo é válida; o segundo retorna os nomes encontrados.

modelo = Template("Olá $nome, pedido $codigo")
if not modelo.is_valid():
    raise ValueError("Modelo inválido")
campos = modelo.get_identifiers()
faltantes = set(campos) - {"nome", "codigo"}
print(campos, faltantes)

Essa validação é útil antes de salvar um template criado por usuário. Você pode permitir somente campos aprovados, rejeitar nomes desconhecidos e mostrar uma mensagem amigável. Também ajuda a criar testes automatizados para garantir que uma tradução continue usando o conjunto correto de variáveis.

Personalizando o delimitador

A classe pode ser estendida para alterar o delimitador. Isso resolve conflitos quando o cifrão já possui outro significado no domínio do texto.

class ModeloArroba(Template):
    delimiter = "@"

modelo = ModeloArroba("Olá @nome")
print(modelo.substitute(nome="Carlos"))

Também é possível personalizar a expressão regular de identificação, mas essa decisão deve ser tomada com cuidado. Quanto mais complexa a sintaxe, maior o custo de manutenção. Na maioria dos projetos, mudar apenas o delimitador ou manter o padrão é suficiente.

Exemplo: gerador de e-mails

Considere um sistema que envia mensagens em vários contextos. O assunto e o corpo podem ficar em arquivos separados. O código carrega o modelo, valida os identificadores e aplica os dados.

from pathlib import Path
from string import Template

def renderizar(caminho, dados):
    conteudo = Path(caminho).read_text(encoding="utf-8")
    modelo = Template(conteudo)
    if not modelo.is_valid():
        raise ValueError("Template com sintaxe inválida")
    permitidos = set(dados)
    desconhecidos = set(modelo.get_identifiers()) - permitidos
    if desconhecidos:
        raise ValueError(f"Campos não permitidos: {desconhecidos}")
    return modelo.substitute(dados)

Esse design mantém o conteúdo fora da função e facilita a revisão por equipes de marketing ou suporte. A função continua responsável por validação, codificação e preenchimento. Para organização de caminhos, consulte pathlib no Python.

Cuidados de segurança

Template evita a avaliação de expressões Python, mas não substitui validações específicas do destino. Se o resultado será exibido em HTML, aplique escape de HTML aos valores. Se será usado em uma consulta SQL, utilize parâmetros do driver; nunca monte SQL por substituição textual. Se será enviado ao terminal, evite concatenar comandos e prefira listas de argumentos no subprocess.

Outro cuidado é limitar os campos aceitos. Um modelo vindo de usuário pode solicitar nomes inesperados e revelar dados que estavam no dicionário. Em vez de passar um objeto inteiro com informações sensíveis, crie um mapping mínimo contendo somente os valores necessários.

Testando modelos

Testes devem cobrir o caminho completo e os erros esperados. Verifique modelos válidos, chaves ausentes, placeholders repetidos, delimitadores escapados com $$ e caracteres junto aos identificadores.

def test_modelo():
    modelo = Template("$nome pagou $$ $valor")
    assert modelo.substitute(nome="Lu", valor="20") == "Lu pagou $ 20"

Também teste traduções. Um modelo em espanhol pode usar os mesmos nomes internos, embora o texto mude. Isso evita que a aplicação precise criar dicionários diferentes para cada idioma.

Boas práticas

Prefira nomes de placeholder claros, como $nome_cliente, em vez de abreviações. Documente os campos disponíveis perto do editor de templates. Valide o modelo no momento do cadastro, não apenas no envio. Use substitute em produção quando dados incompletos devem bloquear a operação e reserve safe_substitute para prévias ou rascunhos.

Mantenha formatação complexa no código. Se um valor monetário precisa de duas casas decimais, formate-o antes de colocá-lo no mapping. Dessa forma, o template permanece simples e previsível.

Conclusão

string.Template oferece uma solução pequena, legível e adequada para conteúdo configurável. Ele não pretende substituir mecanismos completos como Jinja, mas atende muito bem mensagens, notificações e arquivos simples. Ao validar identificadores, limitar dados disponíveis e aplicar escape adequado ao destino, você cria modelos fáceis de editar sem misturar apresentação com lógica de execução.

Documentação oficial: Template strings no Python. Referência de segurança para HTML: html.escape.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Equipe sincronizada representando asyncio.Barrier no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    asyncio.Barrier: sincronize tarefas por etapas

    Aprenda asyncio.Barrier no Python para sincronizar tarefas em fases, evitar corridas e coordenar pipelines assíncronos com segurança.

    Ler mais

    Tempo de leitura: 5 minutos
    08/09/2026
    Desenvolvedor criando modelos com dataclasses.KW_ONLY no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    dataclasses.KW_ONLY: exija argumentos nomeados

    Aprenda dataclasses.KW_ONLY no Python para criar APIs com argumentos nomeados, evitar chamadas ambíguas e evoluir modelos com segurança.

    Ler mais

    Tempo de leitura: 5 minutos
    08/09/2026
    Desenvolvedor usando operator.methodcaller em código Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    operator.methodcaller: chame métodos em pipelines

    Aprenda operator.methodcaller no Python para chamar métodos em map, sorted e pipelines com argumentos e código mais declarativo.

    Ler mais

    Tempo de leitura: 5 minutos
    07/09/2026
    Estrutura de pastas percorrida com pathlib.Path.walk no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    pathlib.Path.walk: percorra e filtre diretórios

    Aprenda a percorrer diretórios com pathlib.Path.walk no Python, filtrar arquivos, ignorar pastas e evitar armadilhas comuns.

    Ler mais

    Tempo de leitura: 5 minutos
    07/09/2026
    Código Python validado com enum.verify
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    enum.verify: valide regras de Enum no Python

    Aprenda enum.verify no Python para validar valores únicos, sequências contínuas e flags nomeadas com regras explícitas.

    Ler mais

    Tempo de leitura: 6 minutos
    06/09/2026
    Grafo de dependências e fluxo de tarefas com TopologicalSorter no Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    TopologicalSorter: ordene dependências sem ciclos

    Aprenda TopologicalSorter no Python para ordenar dependências, detectar ciclos e executar pipelines sequenciais ou paralelos com segurança.

    Ler mais

    Tempo de leitura: 6 minutos
    06/09/2026