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.







