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

    Código Python assíncrono em notebook para inspect.markcoroutinefunction
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    markcoroutinefunction: identifique wrappers async

    Aprenda inspect.markcoroutinefunction no Python para identificar wrappers assíncronos, integrar frameworks e evitar detecção incorreta de corrotinas.

    Ler mais

    Tempo de leitura: 6 minutos
    10/10/2026
    Código Python para percorrer pastas e arquivos com Path.walk
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    Path.walk: percorra diretórios com segurança

    Aprenda Path.walk no Python para percorrer diretórios, filtrar arquivos, tratar erros e controlar a travessia com segurança.

    Ler mais

    Tempo de leitura: 6 minutos
    10/10/2026
    Depuração de processo Python em terminal com código
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    pdb -p: depure processos Python em execução

    Aprenda a anexar o pdb a um processo Python em execução, inspecionar pilhas e diagnosticar travamentos com segurança.

    Ler mais

    Tempo de leitura: 6 minutos
    09/10/2026
    Código Python e representação de frações numéricas
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    fractions.from_number: converta números em frações

    Aprenda fractions.from_number no Python para converter números em frações exatas, controlar precisão e evitar arredondamentos inesperados.

    Ler mais

    Tempo de leitura: 5 minutos
    09/10/2026
    Desenvolvedor configurando servidor HTTPS e certificado TLS com Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    HTTPSServer: crie servidor HTTPS local no Python

    Aprenda HTTPSServer no Python para servir HTTPS localmente, configurar certificados, usar threads e entender limites de segurança.

    Ler mais

    Tempo de leitura: 5 minutos
    08/10/2026
    Arquivos protegidos representando extração segura de TAR com Python
    Python Avançado
    Foto de perfil de Leandro Hirt da Academify

    tarfile extraction_filter: extraia TAR com segurança

    Aprenda tarfile extraction_filter no Python para extrair arquivos TAR com validação, segurança e controle de caminhos.

    Ler mais

    Tempo de leitura: 6 minutos
    08/10/2026