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 или кодировочное cookie в соответствии с PEP 263.

tokenize.generate_tokens(readline)

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

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

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

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

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

tokenize.untokenize(iterable)

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

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

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

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

tokenize.detect_encoding(readline)

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

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

Она обнаруживает кодировку по наличию BOM UTF-8 или кодировочного cookie, как указано в PEP 263. Если присутствуют как BOM, так и cookie, но они не совпадают, будет поднято исключение 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

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

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

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

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

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

-h, --help

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

-e, --exact

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

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

Примеры

Пример скрипта-ревизора, который преобразует литералы с плавающей точкой в объекты 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–2024 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.13/library/tokenize.html

Spec-Zone.ru

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