Spec-Zone.ru › Python 3.10

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. Итерируемый объект должен возвращать последовательности с по крайней мере двумя элементами, типом токена и строкой токена. Любые дополнительные элементы последовательности игнорируются.

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

Он возвращает байты, закодированные с помощью токена 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, за которым следует токенизация их содержимого.

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

Новое в версии 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–2023 Python Software Foundation
Licensed under the PSF License.
https://docs.python.org/3.10/library/tokenize.html

Spec-Zone.ru

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