# `tokenize` — Tokenizador para código-fonte Python

Código-fonte: Lib/tokenize.py

O módulo `tokenize` fornece um scanner léxico para código-fonte Python, implementado em Python. O scanner neste módulo retorna comentários como tokens também, tornando-o útil para implementar “pretty-printers”, incluindo colorizadores para exibições na tela.

Para simplificar o tratamento do fluxo de tokens, todos os tokens operadores e delimitadores e `Ellipsis` são retornados usando o tipo de token genérico `OP`. O tipo exato pode ser determinado verificando a propriedade `exact_type` na tupla nomeada retornada de `tokenize.tokenize()`.

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.

## Tokenizando entradas

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étodo `io.IOBase.readline()` de objetos arquivo. Cada chamada para a função deve retornar uma linha de entrada como bytes.

  O gerador produz tuplas de 5 elementos com estes membros: o tipo de token; a string de token; uma tupla de 2 elementos `(srow, scol)` de ints especificando a linha e a coluna onde o token começa na fonte; uma tupla de 2 elementos `(erow, ecol)` de ints especificando a linha e a coluna onde o token termina na fonte; e a linha na qual o token foi encontrado. A linha passada (o último item da tupla) é a linha física. A tupla 5 elementos é retornada como uma tupla nomeada com os nomes dos campos: `tipo string início fim linha`.

  A tupla nomeada retornada tem uma propriedade adicional chamada `exact_type` que contém o tipo exato do operador para tokens `OP`. Para todos os outros tipos de token, `exact_type` é igual ao campo `type` da tupla nomeada.

  Alterado na versão 3.1: Adiciona suporte para tuplas nomeadas.

  Alterado na versão 3.3: Adicionado suporte para `exact_type`.

  `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.

  O resultado é um iterador produzindo tuplas nomeadas, exatamente como `tokenize()`. Ele não produz um token `ENCODING`.

Todas as constantes do módulo `token` também são exportadas de `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 por `tokenize()`. 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 gerador `tokenize()`.

  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 `SyntaxError` será 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 usa `detect_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.

O módulo `tokenize` pode ser executado como um script a partir da linha de comando. É tão simples quanto:

    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.

## 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()

será tokenizado para a seguinte saída, onde a primeira coluna é o intervalo das coordenadas da linha/coluna onde o token é encontrado, a segunda coluna é o nome do token e a coluna final é o valor do token (se houver)

    $ 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)