Ferramentas que analisam código-fonte precisam distinguir identificadores, números, strings, comentários, operadores, indentação e fim de arquivo. O módulo token no Python fornece as constantes numéricas e os mapas usados para representar esses elementos léxicos em tokenizadores, parsers, depuradores e transformadores de código.
Neste guia, você aprenderá a usar tok_name, EXACT_TOKEN_TYPES, ISTERMINAL(), ISNONTERMINAL() e ISEOF(), além de compreender NAME, NUMBER, STRING, OP, INDENT, DEDENT, f-strings e template strings. O conteúdo complementa nossos artigos sobre tokenize no Python, keyword, symtable, bytecode com dis e codeop.
O papel do módulo token
O arquivo token.py oferece nomes estáveis para categorias de tokens, mas os valores numéricos associados a esses nomes podem mudar entre versões do Python. Por isso, uma ferramenta deve comparar com constantes como token.NAME, não com números copiados de uma execução específica.
import token
print(token.NAME)
print(token.NUMBER)
print(token.STRING)
print(token.tok_name[token.NAME])A documentação oficial de token ressalta que as constantes representam nós terminais da gramática e espelham definições internas do parser.
token e tokenize não são a mesma coisa
O módulo token define constantes e mapas. O módulo tokenize lê bytes ou texto e produz uma sequência de tokens com tipo, conteúdo, posição inicial, posição final e linha original.
import io
import token
import tokenize
codigo = b"total = preco + imposto\n"
for item in tokenize.tokenize(io.BytesIO(codigo).readline):
nome = token.tok_name.get(item.type, str(item.type))
print(nome, item.string)Em outras palavras, token é o vocabulário; tokenize é um scanner que utiliza esse vocabulário.
Usar tok_name
token.tok_name é um dicionário que converte o código numérico para um nome legível.
for codigo, nome in sorted(token.tok_name.items()):
print(codigo, nome)Esse mapa é essencial para logs, relatórios e ferramentas visuais. Exibir NAME é muito mais informativo que mostrar apenas um inteiro.
O token NAME
NAME representa identificadores e palavras que ainda precisam ser interpretadas pelo parser.
codigo = b"for item in itens:\n print(item)\n"Textos como for, item, in, itens e print podem aparecer inicialmente como nomes dependendo da API e das opções. Para saber se uma string é keyword ou soft keyword, combine o valor textual com o módulo keyword.
import keyword
if item.type == token.NAME:
if keyword.iskeyword(item.string):
categoria = "keyword"
elif keyword.issoftkeyword(item.string):
categoria = "soft keyword"
else:
categoria = "identificador"NUMBER
NUMBER representa literais numéricos como inteiros, floats, complexos e números escritos em bases diferentes.
valores = b"10 3.14 0xff 1_000 2j\n"O token preserva o texto original. Ele não converte automaticamente 0xff para inteiro nem remove underscores. Para interpretar o valor, use o parser ou uma função segura adequada ao formato.
STRING
STRING representa strings e bytes comuns. O texto inclui prefixo, aspas e escapes sem processá-los.
codigo = b"nome = r'C:\\temp'\n"Uma ferramenta de estilo pode preservar a escolha de aspas porque recebe o lexema original. Para obter o valor real de um literal confiável, ast.literal_eval() é mais apropriado que eval().
COMMENT
COMMENT identifica comentários quando a sequência vem de tokenize.
# comentário de configuração
limite = 10 # valor máximoO parser normalmente ignora comentários, mas formatadores, linters e refatoradores precisam preservá-los. Essa é uma das razões para usar tokenize em vez de trabalhar apenas com AST.
NEWLINE e NL
NEWLINE encerra uma linha lógica. NL representa uma quebra física que não encerra a instrução, por exemplo dentro de parênteses.
resultado = (
primeiro
+ segundo
)As quebras internas produzem NL; o fim da expressão produz NEWLINE. Essa distinção ajuda formatadores a preservar layout e detectores de entrada interativa a saber se um comando terminou.
INDENT e DEDENT
Python representa blocos por indentação. INDENT marca a entrada em um bloco, enquanto DEDENT marca a saída.
if ativo:
executar()
registrar()
finalizar()O token INDENT contém o prefixo de espaços ou tabs. Um analisador pode comparar estilos, mas deve deixar a validação de ambiguidade para o tokenizer e ferramentas como tabnanny.
ENCODING
tokenize.tokenize() trabalha com bytes e começa a sequência com ENCODING.
with open("modulo.py", "rb") as arquivo:
tokens = list(tokenize.tokenize(arquivo.readline))
print(tokens[0].type == token.ENCODING)A codificação é detectada de acordo com as regras do Python, incluindo BOM e declaração na primeira ou segunda linha. Já tokenize.generate_tokens() trabalha com strings e não produz esse token.
ENDMARKER
ENDMARKER indica o final da entrada e aparece depois da última linha.
ultimo = tokens[-1]
assert ultimo.type == token.ENDMARKERFerramentas que consomem streams devem processar esse marcador para fechar estruturas e validar que toda a entrada foi lida.
OP e operadores exatos
O módulo tokenize costuma reportar operadores e delimitadores como OP.
codigo = b"resultado += valor ** 2\n"Para distinguir +=, **, parênteses e outros símbolos, consulte TokenInfo.exact_type.
for item in tokenize.tokenize(io.BytesIO(codigo).readline):
if item.type == token.OP:
print(item.string, token.tok_name[item.exact_type])Assim, o token genérico OP pode ser refinado para PLUSEQUAL, DOUBLESTAR, LPAR e outras constantes.
EXACT_TOKEN_TYPES
token.EXACT_TOKEN_TYPES mapeia o texto de operadores e delimitadores para o tipo exato.
print(token.EXACT_TOKEN_TYPES["+"] == token.PLUS)
print(token.EXACT_TOKEN_TYPES[":="] == token.COLONEQUAL)
print(token.EXACT_TOKEN_TYPES["->"] == token.RARROW)Esse mapa é útil quando uma ferramenta já possui o texto do símbolo e precisa obter a constante correspondente.
Operadores e delimitadores importantes
O módulo define constantes para parênteses, colchetes, chaves, vírgula, dois-pontos, ponto, operadores aritméticos, comparações, atribuições compostas, seta de anotação, walrus e outros símbolos.
Não construa uma tabela manual. Novas versões podem acrescentar tokens, como ocorreu com COLONEQUAL e EXCLAMATION.
F-strings
Versões atuais expõem tokens específicos para partes de f-strings: FSTRING_START, FSTRING_MIDDLE e FSTRING_END.
mensagem = f"Olá, {usuario.nome}!"O início inclui prefixo e aspas de abertura. O conteúdo literal aparece em partes intermediárias, enquanto expressões de substituição usam os tokens normais do Python delimitados por chaves e símbolos de formatação.
Ferramentas que analisam f-strings devem testar a versão alvo, porque a tokenização evoluiu junto com a gramática.
Template strings no Python 3.14
O Python 3.14 adicionou TSTRING_START, TSTRING_MIDDLE e TSTRING_END para template string literals.
Uma ferramenta compatível com várias versões não deve presumir que essas constantes existem.
if hasattr(token, "TSTRING_START"):
suporte_tstring = TrueUse detecção de recurso ou uma matriz explícita por versão, especialmente em linters distribuídos como pacote.
SOFT_KEYWORD
SOFT_KEYWORD existe como constante para usos internos, mas o módulo tokenize não a produz normalmente. Uma soft keyword tende a chegar como NAME.
if item.type == token.NAME and keyword.issoftkeyword(item.string):
print("soft keyword potencial")O contexto sintático decide se a palavra realmente exerce função especial. Para certeza estrutural, analise a AST.
ERRORTOKEN
ERRORTOKEN representa entrada inválida em algumas situações. Entretanto, tokenize também pode lançar exceções como TokenError ou produzir tokens que só serão rejeitados posteriormente pelo parser.
try:
tokens = list(tokenize.generate_tokens(iter([codigo]).__next__))
except tokenize.TokenError as erro:
print("entrada incompleta ou inválida", erro)Não dependa apenas de ERRORTOKEN para validar sintaxe.
TYPE_COMMENT e TYPE_IGNORE
TYPE_COMMENT e TYPE_IGNORE são usados em fluxos que reconhecem comentários de tipagem com flags específicas do compilador.
x = carregar() # type: Resultado
ignorar() # type: ignoreO tokenizer público não produz esses tipos em todos os modos. Ferramentas de tipagem geralmente trabalham com AST configurada para preservar type comments.
ISTERMINAL()
token.ISTERMINAL(valor) informa se o código representa um token terminal.
print(token.ISTERMINAL(token.NAME))Essa função aparece principalmente em ferramentas que lidam com árvores do parser ou tabelas de gramática.
ISNONTERMINAL()
ISNONTERMINAL() verifica valores de símbolos não terminais, que representam regras compostas da gramática.
def classificar(codigo):
if token.ISTERMINAL(codigo):
return "terminal"
if token.ISNONTERMINAL(codigo):
return "não terminal"
return "desconhecido"APIs modernas costumam usar AST em vez da antiga árvore concreta, mas essas funções ainda são úteis em infraestrutura de parsing.
ISEOF()
ISEOF() identifica o marcador de fim da entrada.
assert token.ISEOF(token.ENDMARKER)Ele evita acoplamento a um número específico e mantém a intenção explícita.
N_TOKENS
N_TOKENS indica a quantidade de tipos de token definida pela versão atual.
print(token.N_TOKENS)Não use esse valor para persistir um formato próprio sem versão. A quantidade e os códigos podem mudar.
Valores mudam entre versões
A documentação deixa claro que os números não são uma API estável entre releases. Salvar apenas o inteiro em banco e interpretá-lo em outro Python pode produzir significado incorreto.
Ao persistir resultados, grave o nome simbólico e a versão do Python.
registro = {
"python": platform.python_version(),
"tipo": token.tok_name[item.type],
"texto": item.string,
}Formatadores e refatoradores
Uma ferramenta que precisa preservar comentários e espaçamento pode transformar a sequência de tokens e reconstruir o código com tokenize.untokenize().
novos = []
for item in tokens:
if item.type == token.NAME and item.string == "antigo_nome":
item = item._replace(string="novo_nome")
novos.append(item)
resultado = tokenize.untokenize(novos)Renomear corretamente exige análise de escopo. Combine tokens com symtable ou AST para evitar trocar atributos, variáveis locais e textos sem relação.
Linters
Linters podem detectar operadores proibidos, comentários especiais, números com estilo inconsistente e indentação. O tipo exato melhora a precisão.
if item.exact_type == token.COLONEQUAL:
registrar_uso_walrus(item.start)Associe sempre posição e linha original ao diagnóstico.
Testar em várias versões
Crie uma matriz de CI com todas as versões suportadas. Verifique tokens adicionados ou removidos, comportamento de f-strings, soft keywords e operadores.
def test_operador_exato():
assert token.EXACT_TOKEN_TYPES["**"] == token.DOUBLESTARNão baseie compatibilidade apenas no número principal. Mudanças podem ocorrer em releases menores da ferramenta que você usa.
Segurança
Tokenizar não executa o código, mas também não garante segurança. Um arquivo pode consumir muita memória, explorar casos extremos do parser ou conter código malicioso que será perigoso se executado depois.
Defina limites de tamanho, tempo e profundidade. Nunca passe automaticamente o resultado para eval() ou exec().
Erros frequentes
- Comparar tipos com números literais.
- Confundir
tokencomtokenize. - Tratar todo
OPcomo o mesmo operador. - Ignorar
exact_type. - Confundir
NLeNEWLINE. - Presumir que soft keywords chegam como
SOFT_KEYWORD. - Persistir códigos sem a versão do Python.
- Executar código apenas porque foi tokenizado com sucesso.
Boas práticas
- Compare com constantes simbólicas.
- Use
tok_nameem logs. - Consulte
exact_typepara operadores. - Preserve posição e linha original.
- Detecte recursos novos com segurança.
- Teste todas as versões suportadas.
- Combine tokens com AST e symtable.
- Imponha limites a entradas externas.
Conclusão
O módulo token no Python define o vocabulário usado para classificar elementos léxicos do código-fonte. Ele fornece constantes legíveis para nomes, números, strings, operadores, indentação, f-strings, template strings e marcadores internos.
Usado junto com tokenize, keyword, AST e tabelas de símbolos, ele permite construir analisadores e transformadores precisos sem depender de números instáveis. A regra principal é simples: trabalhe com nomes simbólicos, considere a versão do Python e nunca confunda análise sintática com execução segura.





