tokenize — Tokenizador para código-fonte Python¶
Código-fonte: Lib/tokenize.py
The tokenize module provides a lexical scanner for Python source code,
implemented in Python. The scanner in this module returns comments as tokens
as well, making it useful for implementing “pretty-printers”, including
colorizers for on-screen displays.
To simplify token stream handling, all operator and
delimiter tokens and Ellipsis are returned using
the generic OP token type.
The TokenInfo.exact_type property gives the exact token type.
Aviso
Observe que as funções neste módulo são projetadas apenas para analisar código Python sintaticamente válido (código que não levanta exceção quando analisado usando ast.parse()). O comportamento das funções neste módulo é indefinido ao fornecer código Python inválido e pode mudar a qualquer momento.
Tokenizing input¶
O ponto de entrada principal é um gerador:
- tokenize.tokenize(readline)¶
O gerador
tokenize()requer um argumento, readline, que deve ser um objeto chamável que fornece a mesma interface que o métodoio.IOBase.readline()de objetos arquivo. Cada chamada para a função deve retornar uma linha de entrada como bytes.The generator produces
TokenInfoobjects.Alterado na versão 3.1: Changed to yield
TokenInfoobjects instead of plain tuples.tokenize()determina a codificação de origem do arquivo procurando por um BOM UTF-8 ou cookie de codificação, de acordo com PEP 263.
- tokenize.generate_tokens(readline)¶
Tokeniza uma fonte lendo strings unicode em vez de bytes.
Assim como
tokenize(), o argumento readline é um chamável que retorna uma única linha de entrada. No entanto,generate_tokens()espera que readline retorne um objeto str em vez de bytes.The result is an iterator yielding
TokenInfoobjects, exactly liketokenize(). It does not yield anENCODINGtoken.
- class tokenize.TokenInfo(type, string, start, end, line)¶
A named tuple describing a token. It has five fields and an additional
exact_typeproperty.Adicionado na versão 3.1.
- type¶
An integer identifying the token type, as defined by the constants in
token, such asNAMEandSTRING. Operators and delimiters have typeOP; useexact_typefor their specific token type.
- string¶
The token text as a
str. ForSTRINGtokens, this includes the quotes, any prefix, and escape sequences, without evaluating them.For an
ENCODINGtoken, this is the encoding name. Tokens inserted without corresponding source text can have an empty string. InFSTRING_MIDDLEandTSTRING_MIDDLEtokens, doubled braces are replaced by single braces.
- start¶
A 2-tuple
(srow, scol)of ints specifying the inclusive start position of the token in the source. Rows are numbered from 1 and columns from 0. Columns count Unicode code points; a tab counts as one column, without expanding it to a tab stop.For an
ENCODINGtoken, this is(0, 0).
- end¶
A 2-tuple
(erow, ecol)of ints specifying the exclusive end position of the token. Rows are numbered from 1 and columns from 0. For a token spanning multiple lines, erow is the final row and ecol is the column on that row.For example, the name
spamat the beginning of the first line hasstartequal to(1, 0)andendequal to(1, 4).For an
ENCODINGtoken, this is(0, 0). ANEWLINEorNLtoken inserted at the end of input without a final newline can have an end column one beyond the source text.
All constants from the token module are also exported from
tokenize.
Outra função é fornecida para reverter o processo de tokenização. Isso é útil para criar ferramentas que tokenizam um script, modificam o fluxo de tokens e escrevem de volta o script modificado.
- tokenize.untokenize(iterable)¶
Converte tokens de volta para o código-fonte Python. O iterable deve retornar sequências com pelo menos dois elementos, o tipo de token e a string do token. Quaisquer elementos de sequência adicionais são ignorados.
O resultado é garantido para tokenizar de volta para corresponder à entrada, de modo que a conversão seja sem perdas e as viagens de ida e volta sejam garantidas. A garantia se aplica somente ao tipo de token e à sequência de tokens, pois o espaçamento entre os tokens (posições de coluna) pode mudar.
Retorna bytes, codificados usando o token
ENCODING, que é a primeira sequência de tokens gerada portokenize(). Se não houver nenhum token de codificação na entrada, ele retorna um str em vez disso.
tokenize() precisa detectar a codificação dos arquivos fonte que ele tokeniza. A função que ele usa para fazer isso está disponível:
- tokenize.detect_encoding(readline)¶
A função
detect_encoding()é usada para detectar a codificação que deve ser usada para decodificar um arquivo de origem Python. Ela requer um argumento, readline, da mesma forma que o geradortokenize().Ele chamará readline no máximo duas vezes e retornará a codificação usada (como uma string) e uma lista de todas as linhas (não decodificadas de bytes) que ele leu.
Ele detecta a codificação a partir da presença de um BOM UTF-8 ou um cookie de codificação conforme especificado em PEP 263. Se um BOM e um cookie estiverem presentes, mas discordarem, uma exceção
SyntaxErrorserá levantada. Observe que se o BOM for encontrado,'utf-8-sig'será retornado como uma codificação.Se nenhuma codificação for especificada, o padrão
'utf-8'será retornado.Use
open()para abrir arquivos de código-fonte Python: ele usadetect_encoding()para detectar a codificação do arquivo.
- tokenize.open(filename)¶
Abre um arquivo no modo somente leitura usando a codificação detectada por
detect_encoding().Adicionado na versão 3.2.
- exception tokenize.TokenError¶
Levantada quando uma docstring ou expressão que pode ser dividida em várias linhas não é concluída em nenhum lugar do arquivo, por exemplo:
"""Início da docstring
ou:
[1, 2, 3
Uso na linha de comando¶
Adicionado na versão 3.3.
The tokenize module can be executed as a script from the command line.
It is as simple as:
python -m tokenize [-e] [nome-do-arquivo.py]
As seguintes opções são aceitas:
- -h, --help¶
mostra esta mensagem de ajuda e sai
- -e, --exact¶
exibe nomes de tokens usando o tipo exato
Se nome-de-arquivo.py for especificado, seu conteúdo será tokenizado para stdout. Caso contrário, a tokenização será realizada em stdin.
Adicionado na versão 3.15: A saída é colorida por padrão e ela pode ser controlada usando variáveis de ambiente.
Exemplos¶
Exemplo de um reescritor de script que transforma literais float em objetos Decimal:
from tokenize import tokenize, untokenize, NUMBER, STRING, NAME, OP
from io import BytesIO
def decistmt(s):
"""Substitui Decimals por floats em uma string de instruções.
>>> from decimal import Decimal
>>> s = 'print(+21.3e-5*-.1234/81.7)'
>>> decistmt(s)
"print (+Decimal ('21.3e-5')*-Decimal ('.1234')/Decimal ('81.7'))"
O formato do expoente é herdado da biblioteca da plataforma C. Casos
conhecidos são "e-007" (Windows) e "e-07" (não Windows). Como estamos
mostrando apenas 12 dígitos, e o 13º não está próximo de 5, o restante
da saída deve ser independente da plataforma.
>>> exec(s) #doctest: +ELLIPSIS
-3.21716034272e-0...7
A saída dos cálculos com Decimal deve ser idêntica em todas as
plataformas.
>>> exec(decistmt(s))
-3.217160342717258261933904529E-7
"""
result = []
g = tokenize(BytesIO(s.encode('utf-8')).readline) # tokenize the string
for toknum, tokval, _, _, _ in g:
if toknum == NUMBER and '.' in tokval: # replace NUMBER tokens
result.extend([
(NAME, 'Decimal'),
(OP, '('),
(STRING, repr(tokval)),
(OP, ')')
])
else:
result.append((toknum, tokval))
return untokenize(result).decode('utf-8')
Exemplo de tokenização a partir da linha de comando. O script:
def say_hello():
print("Hello, World!")
say_hello()
will be tokenized to the following output where the first column is the range of the line/column coordinates where the token is found, the second column is the name of the token, and the final column is the value of the token (if any):
$ python -m tokenize hello.py
0,0-0,0: ENCODING 'utf-8'
1,0-1,3: NAME 'def'
1,4-1,13: NAME 'say_hello'
1,13-1,14: OP '('
1,14-1,15: OP ')'
1,15-1,16: OP ':'
1,16-1,17: NEWLINE '\n'
2,0-2,4: INDENT ' '
2,4-2,9: NAME 'print'
2,9-2,10: OP '('
2,10-2,25: STRING '"Hello, World!"'
2,25-2,26: OP ')'
2,26-2,27: NEWLINE '\n'
3,0-3,1: NL '\n'
4,0-4,0: DEDENT ''
4,0-4,9: NAME 'say_hello'
4,9-4,10: OP '('
4,10-4,11: OP ')'
4,11-4,12: NEWLINE '\n'
5,0-5,0: ENDMARKER ''
Os nomes exatos dos tipos de token podem ser exibidos usando a opção -e:
$ python -m tokenize -e hello.py
0,0-0,0: ENCODING 'utf-8'
1,0-1,3: NAME 'def'
1,4-1,13: NAME 'say_hello'
1,13-1,14: LPAR '('
1,14-1,15: RPAR ')'
1,15-1,16: COLON ':'
1,16-1,17: NEWLINE '\n'
2,0-2,4: INDENT ' '
2,4-2,9: NAME 'print'
2,9-2,10: LPAR '('
2,10-2,25: STRING '"Hello, World!"'
2,25-2,26: RPAR ')'
2,26-2,27: NEWLINE '\n'
3,0-3,1: NL '\n'
4,0-4,0: DEDENT ''
4,0-4,9: NAME 'say_hello'
4,9-4,10: LPAR '('
4,10-4,11: RPAR ')'
4,11-4,12: NEWLINE '\n'
5,0-5,0: ENDMARKER ''
Exemplo de tokenização de um arquivo programaticamente, lendo strings unicode em vez de bytes com generate_tokens():
import tokenize
with tokenize.open('hello.py') as f:
tokens = tokenize.generate_tokens(f.readline)
for token in tokens:
print(token)
Ou lendo bytes diretamente com tokenize():
import tokenize
with open('hello.py', 'rb') as f:
tokens = tokenize.tokenize(f.readline)
for token in tokens:
print(token)