Документация Python неофициальный перевод

30.7. tokenize – токенизатор исходного кода Pythontokenize – Tokenizer for Python source

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

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

tokenize.tokenize(readline)

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

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

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

tokenize() определяет кодировку исходного файла, ища BOM UTF-8 или cookie кодировки, в соответствии с 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 максимум дважды и вернёт используемую кодировку (в виде строки) и список любых строк (не декодированных из байтов), которые она прочитала .

Он определяет кодировку по наличию UTF-8 BOM или cookie кодировки, как указано в PEP 263. Если присутствуют и BOM, и cookie, но они не согласуются, будет вызвано исключение SyntaxError.

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

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

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

def decistmt(s):
    """Заменяет значения float на Decimal.

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

    Формат показателя степени наследуется от библиотеки C платформы.
    Известные случаи: "e-007" (Windows) и "e-07" (не Windows). Поскольку
    мы показываем только 12 цифр, а 13-я не близка к 5, остальная
    часть вывода должна быть независимой от платформы.

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

    Результаты вычислений с Decimal должны быть одинаковыми на всех
    платформах.

    >>> exec(decistmt(s))
    -3.217160342717258261933904529E-7
    """
    result = []
    g = tokenize(BytesIO(s.encode('utf-8')).readline) # токенизировать строку
    for toknum, tokval, _, _, _  in g:
        if toknum == NUMBER and '.' in tokval:  # заменить токены NUMBER
            result.extend([
                (NAME, 'Decimal'),
                (OP, '('),
                (STRING, repr(tokval)),
                (OP, ')')
            ])
        else:
            result.append((toknum, tokval))
    return untokenize(result).decode('utf-8')