Spec-Zone.ru › Python 3.6

tokenize — Токенизатор для исходного кода Python

Исходный код: Lib/tokenize.py

Модуль tokenize предоставляет лексический анализатор для исходного кода Python, реализованный на Python. Анализатор в этом модуле возвращает комментарии как токены, что делает его полезным для реализации «красивых принтеров», включая цветовые схемы для отображения на экране.

Для упрощения обработки потока токенов, все токены операторов и разделителей и токен Ellipsis возвращаются с использованием универсального типа токена OP. Точный тип можно определить, проверив свойство exact_type у именованной кортежи, возвращаемой из tokenize.tokenize().

32.7.1. Токенизация входных данных

Основной точкой входа является генератор:

tokenize.tokenize(readline)

Генератор tokenize() требует одного аргумента, readline, который должен быть вызываемым объектом, предоставляющим тот же интерфейс, что и метод io.IOBase.readline() объектов файлов. Каждый вызов функции должен возвращать одну строку входных данных в виде байтов.

Генератор создает 5-кортежи с этими членами: тип токена; строка токена; 2-кортеж (srow, scol) целых чисел, указывающих строку и столбец, где начинается токен в исходном коде; 2-кортеж (erow, ecol) целых чисел, указывающих строку и столбец, где заканчивается токен в исходном коде; и строка, на которой был найден токен. Переданная строка (последний элемент кортежа) — это логическая строка; строки продолжения включены. 5-кортеж возвращается как именованная кортеж с именами полей: type string start end line.

Возвращаемый именованная кортеж имеет дополнительное свойство, называемое exact_type, которое содержит точный тип оператора для токенов token.OP. Для всех других типов токенов exact_type равно полю именованной кортежи type.

Изменено в версии 3.1: Добавлена поддержка именованных кортежей.

Изменено в версии 3.3: Добавлена поддержка exact_type.

tokenize() определяет кодировку исходного файла, ища BOM UTF-8 или кодировочный фрагмент, согласно PEP 263.

Все константы из модуля token также экспортируются из tokenize, а также три дополнительных значения типа токена:

tokenize.COMMENT

Значение токена, используемое для обозначения комментария.

tokenize.NL

Значение токена, используемое для обозначения не завершающейся новой строки. Токен NEWLINE указывает конец логической строки кода Python; токены NL генерируются, когда логическая строка кода продолжается на нескольких физических строках.

tokenize.ENCODING

Значение токена, указывающее кодировку, используемую для декодирования байтов исходного текста в текст. Первый токен, возвращаемый tokenize(), всегда будет токеном ENCODING.

Предоставляется еще одна функция для обратного преобразования токенизации. Это полезно для создания инструментов, которые токенизируют скрипт, изменяют поток токенов и записывают обратно изменённый скрипт.

tokenize.untokenize(iterable)

Преобразует токены обратно в исходный код Python. Итерируемый объект должен возвращать последовательности с как минимум двумя элементами, типом токена и строкой токена. Любые дополнительные элементы последовательности игнорируются.

Восстановленный скрипт возвращается как одна строка. Результат гарантированно будет токенизирован в соответствии с входными данными, так что преобразование без потерь и гарантированы обратные преобразования. Гарантия распространяется только на тип и строку токена, поскольку расстояние между токенами (позиции столбцов) может изменяться.

Возвращает байты, закодированные с помощью токена ENCODING, который является первой последовательностью токенов, выведенной tokenize().

tokenize() необходимо обнаруживать кодировку исходных файлов, которые он токенизирует. Функция, которую он использует для этого, доступна:

tokenize.detect_encoding(readline)

Функция detect_encoding() используется для определения кодировки, которая должна быть использована для декодирования файла исходного кода Python. Она требует одного аргумента, readline, аналогично генератору tokenize().

Она вызовет readline не более двух раз и вернет используемую кодировку (как строку) и список любых строк (не декодированных из байтов), которые она прочитала.

Она обнаруживает кодировку по наличию BOM UTF-8 или кодировочного фрагмента, как указано в PEP 263. Если присутствуют как BOM, так и фрагмент, но они не совпадают, будет поднята ошибка SyntaxError. Обратите внимание, что если BOM найден, 'utf-8-sig' будет возвращена как кодировка.

Если кодировка не указана, то вернется значение по умолчанию 'utf-8'.

Используйте open() для открытия файлов исходного кода Python: она использует detect_encoding() для определения кодировки файла.

tokenize.open(filename)

Открывает файл в режиме чтения только для чтения с использованием кодировки, определенной detect_encoding().

Новая в версии 3.2.

exception tokenize.TokenError

Возникает, когда строка документации или выражение, которое может быть разделено на несколько строк, не завершено нигде в файле, например:

"""Beginning of
docstring

или:

[1,
 2,
 3

Обратите внимание, что незакрытые строки в одинарных кавычках не вызывают ошибку. Они токенизируются как ERRORTOKEN, за которым следует токенизация их содержимого.

32.7.2. Использование в командной строке

Новая в версии 3.3.

Модуль tokenize может быть выполнен как скрипт из командной строки. Это так же просто, как:

python -m tokenize [-e] [filename.py]

Принимаются следующие опции:

-h, --help

показать это сообщение справки и выйти

-e, --exact

отобразить имена токенов с использованием точного типа

Если filename.py указан, его содержимое токенизируется в стандартный вывод. В противном случае токенизация выполняется на стандартном вводе.

32.7.3. Примеры

Пример скрипта-переработчика, который преобразует литералы чисел с плавающей точкой в объекты Decimal:

from tokenize import tokenize, untokenize, NUMBER, STRING, NAME, OP
from io import BytesIO

def decistmt(s):
    """Substitute Decimals for floats in a string of statements.

    >>> from decimal import Decimal
    >>> s = 'print(+21.3e-5*-.1234/81.7)'
    >>> decistmt(s)
    "print (+Decimal ('21.3e-5')*-Decimal ('.1234')/Decimal ('81.7'))"

    The format of the exponent is inherited from the platform C library.
    Known cases are "e-007" (Windows) and "e-07" (not Windows).  Since
    we're only showing 12 digits, and the 13th isn't close to 5, the
    rest of the output should be platform-independent.

    >>> exec(s)  #doctest: +ELLIPSIS
    -3.21716034272e-0...7

    Output from calculations with Decimal should be identical across all
    platforms.

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

Пример токенизации из командной строки. Скрипт:

def say_hello():
    print("Hello, World!")

say_hello()

будет токенизирован со следующим выводом, где первый столбец — это диапазон координат строки/столбца, где находится токен, второй столбец — это имя токена, а последний столбец — это значение токена (если есть)

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

Точные имена типов токенов могут быть отображены с помощью опции -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      ''

© 2001–2020 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.6/library/tokenize.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API