Spec-Zone.ru › Python 3.13

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

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

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

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

Предупреждение

Обратите внимание: функции этого модуля предназначены только для разбора синтаксически корректного кода Python (кода, который не вызывает исключений при разборе с помощью ast.parse()). Поведение функций этого модуля при передаче некорректного кода Python не определено и может измениться в любой момент.

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

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

tokenize.tokenize(readline)

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

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

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

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

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

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

tokenize.generate_tokens(readline)

Токенизирует исходный текст, читая строки Unicode вместо байтов.

Как и tokenize(), аргумент readline должен быть вызываемым объектом, возвращающим одну строку входных данных. Однако generate_tokens() ожидает, что readline будет возвращать объект str, а не байты.

Результатом является итератор, выдающий именованные кортежи, точно так же, как tokenize(). Он не выдаёт токен ENCODING.

Все константы из модуля token также экспортируются из tokenize.

Также предусмотрена функция, обратная токенизации. Она полезна для создания инструментов, которые токенизируют скрипт, изменяют поток токенов и записывают изменённый скрипт обратно.

tokenize.untokenize(iterable)

Преобразует токены обратно в исходный код Python. Аргумент iterable должен возвращать последовательности как минимум из двух элементов: типа токена и строки токена. Все дополнительные элементы последовательности игнорируются.

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

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

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

tokenize.detect_encoding(readline)

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

Функция вызовет readline не более двух раз и вернёт использованную кодировку (в виде строки) и список всех прочитанных строк (не декодированных из байтов).

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

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

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

tokenize.open(filename)

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

Добавлено в версии 3.2.

exception tokenize.TokenError

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

"""Beginning of
docstring

или:

[1,
 2,
 3

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

Добавлено в версии 3.3.

Модуль tokenize можно запускать из командной строки как скрипт. Это делается очень просто:

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

Поддерживаются следующие параметры:

-h, --help

показать это справочное сообщение и завершить работу

-e, --exact

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

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

Примеры

Пример скрипта, переписывающего код и преобразующего литералы типа float в объекты 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      ''

Пример программной токенизации файла: чтение строк Unicode вместо байтов с помощью generate_tokens():

import tokenize

with tokenize.open('hello.py') as f:
    tokens = tokenize.generate_tokens(f.readline)
    for token in tokens:
        print(token)

Или непосредственное чтение байтов с помощью tokenize():

import tokenize

with open('hello.py', 'rb') as f:
    tokens = tokenize.tokenize(f.readline)
    for token in tokens:
        print(token)

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

Spec-Zone.ru

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