tokenize no Python: leia tokens do código

Publicado em: 27/08/2026
Tempo de leitura: 7 minutos
Flat lay of gold bitcoin coins on a pink surface, symbolizing cryptocurrency and modern investment.

O módulo tokenize transforma código-fonte Python em uma sequência de tokens. Cada token descreve um fragmento lexical, como nome, número, string, operador, comentário, indentação, quebra de linha ou fim do arquivo. Essa camada é útil em formatadores, linters, conversores, ferramentas de documentação, análise de comentários e pequenas transformações que precisam preservar mais detalhes textuais do que uma AST.

Tokens ainda não representam o significado completo do programa. Eles não resolvem escopos, imports, tipos ou comportamento em runtime. Para análise estrutural, use ast; para símbolos, symtable; para bytecode, dis. tokenize é ideal quando whitespace, comentários, posição e forma literal importam.

Tokens a partir de bytes

A função principal tokenize.tokenize() recebe uma função readline que devolve bytes.

from io import BytesIO
from tokenize import tokenize

codigo = b"x = 10 + 2\n"
for token in tokenize(BytesIO(codigo).readline):
    print(token)

A sequência inclui um token ENCODING, os tokens do código e ENDMARKER.

TokenInfo

Cada item é uma instância de TokenInfo com campos type, string, start, end e line.

for item in tokenize(BytesIO(codigo).readline):
    print(item.type, item.string, item.start, item.end)

start e end são pares de linha e coluna. line contém a linha física original associada ao token.

Nomes legíveis de tipos

Os tipos são inteiros definidos no módulo token. Use token.tok_name para exibir nomes.

import token

nome = token.tok_name[item.type]

Não grave números crus em formatos persistentes; eles são detalhes da versão do Python.

exact_type para operadores

Operadores e delimitadores usam o tipo geral OP, mas TokenInfo.exact_type informa o token exato.

import token

if item.type == token.OP:
    print(token.tok_name[item.exact_type])

Isso permite distinguir +, +=, parênteses, dois-pontos e outros símbolos.

generate_tokens para texto

generate_tokens() aceita uma função que devolve strings, o que é conveniente quando o texto já foi decodificado.

from io import StringIO
from tokenize import generate_tokens

for item in generate_tokens(StringIO("x = 1\n").readline):
    print(item)

Essa API não produz o token ENCODING. Para arquivos reais, prefira a versão baseada em bytes ou tokenize.open().

Encoding do código-fonte

Arquivos Python podem declarar encoding nas primeiras linhas. tokenize() detecta a codificação segundo as regras da linguagem.

Ler o arquivo como UTF-8 antes da detecção pode falhar em projetos legados.

detect_encoding

detect_encoding() recebe uma função de leitura de bytes e devolve o encoding e as linhas já consumidas.

from tokenize import detect_encoding

with open("modulo.py", "rb") as arquivo:
    encoding, linhas = detect_encoding(arquivo.readline)
    print(encoding, linhas)

A função pode precisar ler até duas linhas para verificar BOM e cookie de encoding.

tokenize.open

tokenize.open(filename) abre um arquivo Python em texto usando a codificação detectada.

import tokenize

with tokenize.open("modulo.py") as arquivo:
    codigo = arquivo.read()

Essa é uma escolha segura para ferramentas que precisam ler o fonte como texto.

Comentários

Diferentemente da AST, a tokenização preserva comentários como tokens COMMENT.

import token

comentarios = [
    item for item in tokens
    if item.type == token.COMMENT
]

Isso permite encontrar TODOs, pragmas, type comments e diretivas de ferramentas.

Não trate todo comentário como instrução

Uma diretiva deve possuir sintaxe clara, posição permitida e validação. Buscar apenas uma substring pode produzir falsos positivos.

Defina um prefixo, como # ferramenta:, e faça parsing do restante.

NL e NEWLINE

NEWLINE termina uma instrução lógica. NL representa quebras físicas que não encerram a instrução, por exemplo dentro de parênteses ou em linhas vazias.

resultado = (
    1
    + 2
)

Formatadores e analisadores de linha precisam diferenciar os dois.

Indentação

INDENT e DEDENT representam mudanças de bloco.

if ativo:
    executar()

O valor de INDENT contém o whitespace. Misturas inconsistentes de tabs e espaços podem gerar erros.

TabError e IndentationError

A tokenização ou compilação pode gerar erros quando a indentação é inválida. Capture exceções e mostre arquivo, linha e contexto.

Não tente corrigir automaticamente indentação ambígua sem uma política de formatação.

Strings

Uma string literal inteira aparece normalmente como token STRING, incluindo prefixo e aspas.

r"caminho\arquivo"
f"valor={x}"

A forma exata pode variar conforme recursos da linguagem e versão. Para entender expressões dentro de f-strings, talvez seja necessário combinar tokenizer e parser.

Números

Inteiros, floats, complexos e bases diferentes aparecem como NUMBER com a grafia original.

0xff
1_000_000
3.14e-2

Isso permite preservar underscores e estilo, algo que a AST normalmente normaliza ao representar o valor.

Nomes e palavras-chave

Identificadores e keywords chegam como NAME. Para descobrir se o texto é uma palavra-chave, use keyword.iskeyword().

import keyword

if item.type == token.NAME and keyword.iskeyword(item.string):
    print("keyword", item.string)

Soft keywords dependem do contexto sintático e exigem parser.

untokenize

untokenize()` reconstrói código a partir de tokens.

from tokenize import untokenize

novo_codigo = untokenize(tokens)

O resultado garante round trip do par tipo/string em condições suportadas, mas spacing exato pode mudar.

Transformação simples

Uma ferramenta pode alterar nomes mantendo o restante dos tokens.

import token
from tokenize import TokenInfo, untokenize

novos = []
for item in tokens:
    if item.type == token.NAME and item.string == "antigo":
        item = TokenInfo(
            item.type, "novo", item.start, item.end, item.line
        )
    novos.append(item)

resultado = untokenize(novos)

Renomear corretamente exige considerar escopos, atributos, imports e shadowing. Tokens sozinhos não resolvem semântica.

Pares tipo e string

untokenize() também aceita sequências de pares (type, string). Nesse caso, ele decide o spacing necessário.

Para preservar mais localização, mantenha TokenInfo, mas não presuma que posições antigas continuam válidas depois da edição.

Posições após transformação

Alterar o comprimento de um token torna offsets seguintes desatualizados. A reconstrução usa os tokens, mas diagnósticos baseados nas posições originais precisam ser recalculados.

Uma ferramenta editorial robusta mantém um mapa entre fonte original e novo texto.

Preservação de comentários

Transformações por AST e ast.unparse() normalmente perdem comentários. Tokens permitem preservá-los, mas mudanças estruturais complexas ficam difíceis.

Para refactoring com round trip fiel, considere uma concrete syntax tree.

TokenError

TokenError ocorre em entradas como string multilinha ou parênteses não terminados.

from tokenize import TokenError

try:
    tokens = list(tokenize(readline))
except TokenError as erro:
    print("fonte incompleto", erro)

Em editores, código temporariamente incompleto é normal. Trate o erro sem derrubar toda a análise.

ERRORTOKEN

Alguns caracteres inválidos ou casos especiais aparecem como ERRORTOKEN. Analise o texto e a posição antes de decidir a mensagem.

Whitespace comum também pode aparecer em contextos específicos, portanto não rotule todo ERRORTOKEN como ataque.

Entrada parcial

Uma IDE pode tokenizar buffers enquanto o usuário digita. Implemente debounce, cancelamento e resultados parciais.

Não execute o código para obter tokens.

Arquivos grandes

Converter todo o generator em lista consome memória proporcional ao arquivo. Processe tokens em streaming quando possível.

Transformações que precisam olhar adiante podem usar uma janela limitada.

Limites contra abuso

Entrada não confiável pode conter arquivos enormes, linhas gigantes e nesting extremo. Limite bytes, linhas, tokens e tempo.

Execute análise pesada em processo separado quando fizer parte de um serviço público.

Unicode em identificadores

Python aceita identificadores Unicode. Não presuma ASCII ao validar nomes.

Para políticas de segurança, normalize e detecte caracteres visualmente confusos sem rejeitar idiomas legítimos de forma indiscriminada.

Caracteres invisíveis

Uma ferramenta pode procurar controles, espaços incomuns ou caracteres bidirecionais em comentários e strings. Diferencie presença legítima de risco.

Mostre code points e posições no diagnóstico.

Integração com AST

Use tokens para comentários e estilo e AST para estrutura. Um fluxo comum associa nós a intervalos de linha e encontra tokens no mesmo trecho.

Veja ast no Python para visitors e transformações estruturais.

Integração com symtable

Tokens identificam grafia; symtable ajuda a descobrir escopos, globals, locals e free variables.

Essa combinação é mais segura para renames do que substituir todo token NAME.

Formatadores

Um formatador precisa considerar tokens, árvore sintática, comentários e regras de layout. Apenas inserir espaços ao redor de OP não cobre todos os casos.

Use uma gramática completa e uma suíte grande de testes.

Linters de comentários

Tokenização é suficiente para regras como comprimento de comentários, TODO sem responsável ou pragma inválida.

Ignore strings que contêm #; elas não são tokens COMMENT.

Detecção de secrets

Tokens podem ajudar a encontrar strings associadas a nomes como password e token, mas análise lexical gera falsos positivos.

Nunca registre o valor detectado. Mostre localização e tipo de regra.

Command line

O módulo possui uma interface de linha de comando que exibe tokens de um arquivo.

python -m tokenize modulo.py

É útil para aprender e depurar regras.

Testes

Inclua encoding diferente, BOM, comentários, strings multilinha, f-strings, tabs, linhas vazias, parênteses abertos, Unicode, arquivo incompleto e código muito grande.

Para transformações, tokenize novamente o resultado e compile-o.

Erros comuns

Os erros mais frequentes são ler tudo como UTF-8, confundir NL e NEWLINE, tratar keywords como tipo separado, renomear NAME sem escopo, perder comentários ao migrar para AST, confiar em posições antigas, usar lista para arquivo gigante e não limitar entrada pública.

Conclusão

tokenize oferece acesso detalhado à forma lexical do código Python, preservando comentários, grafia, linhas e operadores. Use tokenize.open() para encoding correto, exact_type para operadores e untokenize() para reconstrução controlada.

Combine tokens com AST e symbol tables quando a transformação precisar entender significado. Consulte a documentação oficial de tokenize e a documentação de token.

Compartilhe:

Facebook
WhatsApp
Twitter
LinkedIn

Conteúdo do artigo

    Artigos relacionados

    Color-coded office binders organized neatly in a storage shelf, featuring labels and a striking red binder.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    zipapp no Python: crie arquivos .pyz

    Aprenda zipapp no Python para criar arquivos .pyz, definir entry points, incluir dependências, usar recursos e distribuir CLIs com segurança.

    Ler mais

    Tempo de leitura: 8 minutos
    27/08/2026
    A laptop screen showing a code editor with visible programming code in a dimly lit environment.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    sysconfig no Python: caminhos e build

    Aprenda sysconfig no Python para descobrir paths, schemes, headers, flags de build, ABI, extensões nativas e detalhes de ambientes virtuais.

    Ler mais

    Tempo de leitura: 7 minutos
    27/08/2026
    A person typing on a laptop with a Python programming book visible, capturing technology and learning.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    marshal no Python: formato interno

    Aprenda marshal no Python para objetos internos e bytecode, entenda versões, allow_code, limites, caches e riscos de dados não confiáveis.

    Ler mais

    Tempo de leitura: 8 minutos
    27/08/2026
    A close-up view of fresh, green cucumbers ready for pickling and preservation in Estonia.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    copyreg no Python: personalize o pickle

    Aprenda copyreg no Python para personalizar pickle, registrar redutores, versionar estado, evitar conflitos globais e serializar com segurança.

    Ler mais

    Tempo de leitura: 8 minutos
    27/08/2026
    Close-up view of a computer screen displaying code in a software development environment.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    reprlib no Python: representações seguras

    Aprenda reprlib no Python para resumir listas, strings e objetos recursivos, limitar logs e criar representações seguras e legíveis.

    Ler mais

    Tempo de leitura: 7 minutos
    27/08/2026
    A close-up shot showcasing the intricate scales of a snake, highlighting texture and color.
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    graphlib no Python: ordenação topológica

    Aprenda graphlib no Python para ordenar dependências, detectar ciclos, executar tarefas prontas em paralelo e criar pipelines seguros.

    Ler mais

    Tempo de leitura: 8 minutos
    27/08/2026