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

tokenize.md

247 строк · 16.7 КБ · обычная страница · сырой текст · скачать

1> **Источник:** https://python-all.ru/3.16/library/tokenize.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# `tokenize` – Токенизатор исходного кода Python89**Исходный код:** [Lib/tokenize.py](https://python-all.ru/src/main/Lib/tokenize.py)1011---1213Модуль `tokenize` предоставляет лексический анализатор для исходного кода Python, реализованный на Python. Анализатор в этом модуле также возвращает комментарии в виде токенов, что делает его полезным для реализации «pretty-printers», включая цветовые выделители для отображения на экране.1415Чтобы упростить обработку потока токенов, все токены [операторов](https://python-all.ru/3.16/reference/lexical_analysis.html#operators) и [разделителей](https://python-all.ru/3.16/reference/lexical_analysis.html#delimiters), а также [`Ellipsis`](https://python-all.ru/3.16/library/constants.html#Ellipsis) возвращаются с использованием общего типа токена [`OP`](https://python-all.ru/3.16/library/token.html#token.OP). Точный tип можно определить, проверив свойство `exact_type` у [именованного кортежа](https://python-all.ru/3.16/glossary.html#term-named-tuple), возвращаемого функцией [`tokenize.tokenize()`](https://python-all.ru/3.16/library/tokenize.html#tokenize.tokenize).1617> **Предупреждение**18>19> Обратите внимание, что функции в этом модуле предназначены только для анализа синтаксически корректного кода Python (кода, который не вызывает ошибок при разборе с помощью [`ast.parse()`](https://python-all.ru/3.16/library/ast.html#ast.parse)). Поведение функций в этом модуле **не определено** при передаче некорректного кода Python и может измениться в любой момент.2021## Токенизация входных данных2223Основной точкой входа является [генератор](https://python-all.ru/3.16/glossary.html#term-generator):2425#### `tokenize.tokenize(readline)`2627Генератор `tokenize()` требует один аргумент, *readline*, который должен быть вызываемым объектом, предоставляющим тот же интерфейс, что и метод [`io.IOBase.readline()`](https://python-all.ru/3.16/library/io.html#io.IOBase.readline) файловых объектов. Каждый вызов функции должен возвращать одну строку входных данных в виде байтов.2829Генератор создаёт 5-кортежи со следующими элементами: тип токена; строка токена; 2-кортеж `(srow, scol)` из целых чисел, указывающих строку и столбец, где токен начинается в исходном коде; 2-кортеж `(erow, ecol)` из целых чисел, указывающих строку и столбец, где токен заканчивается; и строка, в которой был найден токен. Передаваемая строка (последний элемент кортежа) является *физической* строкой. 5-кортеж возвращается в виде [именованного кортежа](https://python-all.ru/3.16/glossary.html#term-named-tuple) с именами полей: `type string start end line`.3031Возвращаемый [именованный кортеж](https://python-all.ru/3.16/glossary.html#term-named-tuple) имеет дополнительное свойство с именем `exact_type`, которое содержит точный тип оператора для токенов [`OP`](https://python-all.ru/3.16/library/token.html#token.OP). Для всех остальных типов токенов `exact_type` равно полю `type` именованного кортежа.3233Изменено в версии 3.1: Добавлена поддержка именованных кортежей.3435Изменено в версии 3.3: Добавлена поддержка `exact_type`.3637`tokenize()` определяет исходную кодировку файла, проверяя наличие UTF-8 BOM или кодировочной метки, в соответствии с [**PEP 263**](https://python-all.ru/3.16/library/tokenize.html).3839#### `tokenize.generate_tokens(readline)`4041Токенизирует исходный код, читая строки Unicode вместо байтов.4243Как и [`tokenize()`](https://python-all.ru/3.16/library/tokenize.html#tokenize.tokenize), аргумент *readline* является вызываемым объектом, возвращающим одну строку входных данных. Однако `generate_tokens()` ожидает, что *readline* будет возвращать объект str, а не bytes.4445Результатом является итератор, возвращающий именованные кортежи, точно как [`tokenize()`](https://python-all.ru/3.16/library/tokenize.html#tokenize.tokenize). Он не возвращает токен [`ENCODING`](https://python-all.ru/3.16/library/token.html#token.ENCODING).4647Все константы из модуля [`token`](https://python-all.ru/3.16/library/token.html#module-token) также экспортируются из `tokenize`.4849Предоставляется ещё одна функция для обращения процесса токенизации. Это полезно для создания инструментов, которые токенизируют скрипт, изменяют поток токенов и записывают изменённый скрипт обратно.5051#### `tokenize.untokenize(iterable)`5253Преобразует токены обратно в исходный код Python. *Итерируемый объект* должен возвращать последовательности как минимум из двух элементов: типа токена и строки токена. Все дополнительные элементы последовательности игнорируются.5455Результат гарантированно токенизируется обратно в соответствии с входными данными, так что преобразование является без потерь, и гарантируется обратимость. Гарантия распространяется только на тип токена и строку токена, так как расстояние между токенами (позиции столбцов) может измениться.5657Он возвращает байты, закодированные с использованием токена [`ENCODING`](https://python-all.ru/3.16/library/token.html#token.ENCODING), который является первым токеном последовательности, выводимой [`tokenize()`](https://python-all.ru/3.16/library/tokenize.html#tokenize.tokenize). Если во входных данных нет токена кодировки, вместо этого возвращается str.5859[`tokenize()`](https://python-all.ru/3.16/library/tokenize.html#tokenize.tokenize) необходимо определить кодировку исходных файлов, которые он токенизирует. Функция, которую он использует для этого, доступна:6061#### `tokenize.detect_encoding(readline)`6263Функция `detect_encoding()` используется для определения кодировки, которая должна использоваться для декодирования файла исходного кода Python. Она требует один аргумент, readline, так же, как генератор [`tokenize()`](https://python-all.ru/3.16/library/tokenize.html#tokenize.tokenize).6465Она вызовет readline максимум дважды и вернёт используемую кодировку (в виде строки) и список любых строк (не декодированных из байтов), которые она прочитала .6667Он определяет кодировку по наличию UTF-8 BOM или кодировочной метки, как указано в [**PEP 263**](https://python-all.ru/3.16/library/tokenize.html). Если присутствуют и BOM, и метка, но они не согласуются, будет возбуждено [`SyntaxError`](https://python-all.ru/3.16/library/exceptions.html#SyntaxError). Обратите внимание: если найден BOM, в качестве кодировки будет возвращена `'utf-8-sig'`.6869Если кодировка не указана, то будет возвращено значение по умолчанию `'utf-8'`.7071Используйте [`open()`](https://python-all.ru/3.16/library/tokenize.html#tokenize.open) для открытия файлов исходного кода Python: он использует `detect_encoding()` для определения кодировки файла.7273#### `tokenize.open(filename)`7475Открывает файл в режиме только для чтения, используя кодировку, определённую с помощью [`detect_encoding()`](https://python-all.ru/3.16/library/tokenize.html#tokenize.detect_encoding).7677Добавлено в версии 3.2.7879#### `exception tokenize.TokenError`8081Возникает, когда докстринг или выражение, которое может быть разбито на несколько строк, не завершено нигде в файле, например:8283```python84"""Beginning of85docstring86```8788или:8990```python91[1,92 2,93 394```9596## Использование командной строки9798Добавлено в версии 3.3.99100Модуль `tokenize` может быть выполнен как скрипт из командной строки. Это просто:101102```sh103python -m tokenize [-e] [filename.py]104```105106Принимаются следующие опции:107108#### `-h, --help`109110показывает это справочное сообщение и завершает работу111112#### `-e, --exact`113114отображает имена токенов с использованием точного типа115116Если указан `filename.py`, его содержимое токенизируется в stdout. В противном случае токенизация выполняется из stdin.117118Добавлено в версии 3.15: Вывод по умолчанию цветной, и его можно [настроить с помощью переменных окружения](https://python-all.ru/3.16/using/cmdline.html#using-on-controlling-color).119120## Примеры121122Пример переписчика скриптов, преобразующего литералы чисел с плавающей запятой в объекты Decimal :123124```python125from tokenize import tokenize, untokenize, NUMBER, STRING, NAME, OP126from io import BytesIO127128def decistmt(s):129    """Заменяет значения float на Decimal.130131    >>> from decimal import Decimal132    >>> s = 'print(+21.3e-5*-.1234/81.7)'133    >>> decistmt(s)134    "print (+Decimal ('21.3e-5')*-Decimal ('.1234')/Decimal ('81.7'))"135136    Формат показателя степени наследуется от библиотеки C платформы.137    Известные случаи: "e-007" (Windows) и "e-07" (не Windows). Поскольку138    мы показываем только 12 цифр, а 13-я не близка к 5, остальная139    часть вывода должна быть независимой от платформы.140141    >>> exec(s)  #doctest: +ELLIPSIS142    -3.21716034272e-0...7143144    Результаты вычислений с Decimal должны быть одинаковыми на всех145    платформах.146147    >>> exec(decistmt(s))148    -3.217160342717258261933904529E-7149    """150    result = []151    g = tokenize(BytesIO(s.encode('utf-8')).readline)  # токенизировать строку152    for toknum, tokval, _, _, _ in g:153        if toknum == NUMBER and '.' in tokval:  # заменить токены NUMBER154            result.extend([155                (NAME, 'Decimal'),156                (OP, '('),157                (STRING, repr(tokval)),158                (OP, ')')159            ])160        else:161            result.append((toknum, tokval))162    return untokenize(result).decode('utf-8')163```164165Пример токенизации из командной строки. Скрипт:166167```python168def say_hello():169    print("Hello, World!")170171say_hello()172```173174будет токенизирован в следующий вывод, где первый столбец – это диапазон координат строки/столбца, в котором найден токен, второй столбец – это название токена, а последний столбец – значение токена (если оно есть):175176```console177$ python -m tokenize hello.py1780,0-0,0:            ENCODING       'utf-8'1791,0-1,3:            NAME           'def'1801,4-1,13:           NAME           'say_hello'1811,13-1,14:          OP             '('1821,14-1,15:          OP             ')'1831,15-1,16:          OP             ':'1841,16-1,17:          NEWLINE        '\n'1852,0-2,4:            INDENT         '    '1862,4-2,9:            NAME           'print'1872,9-2,10:           OP             '('1882,10-2,25:          STRING         '"Hello, World!"'1892,25-2,26:          OP             ')'1902,26-2,27:          NEWLINE        '\n'1913,0-3,1:            NL             '\n'1924,0-4,0:            DEDENT         ''1934,0-4,9:            NAME           'say_hello'1944,9-4,10:           OP             '('1954,10-4,11:          OP             ')'1964,11-4,12:          NEWLINE        '\n'1975,0-5,0:            ENDMARKER      ''198```199200Точные имена типов токенов можно отобразить с помощью опции [`-e`](https://python-all.ru/3.16/library/tokenize.html#cmdoption-tokenize-e):201202```console203$ python -m tokenize -e hello.py2040,0-0,0:            ENCODING       'utf-8'2051,0-1,3:            NAME           'def'2061,4-1,13:           NAME           'say_hello'2071,13-1,14:          LPAR           '('2081,14-1,15:          RPAR           ')'2091,15-1,16:          COLON          ':'2101,16-1,17:          NEWLINE        '\n'2112,0-2,4:            INDENT         '    '2122,4-2,9:            NAME           'print'2132,9-2,10:           LPAR           '('2142,10-2,25:          STRING         '"Hello, World!"'2152,25-2,26:          RPAR           ')'2162,26-2,27:          NEWLINE        '\n'2173,0-3,1:            NL             '\n'2184,0-4,0:            DEDENT         ''2194,0-4,9:            NAME           'say_hello'2204,9-4,10:           LPAR           '('2214,10-4,11:          RPAR           ')'2224,11-4,12:          NEWLINE        '\n'2235,0-5,0:            ENDMARKER      ''224```225226Пример программной токенизации файла: чтение строк Unicode вместо байтов с помощью [`generate_tokens()`](https://python-all.ru/3.16/library/tokenize.html#tokenize.generate_tokens):227228```python229import tokenize230231with tokenize.open('hello.py') as f:232    tokens = tokenize.generate_tokens(f.readline)233    for token in tokens:234        print(token)235```236237Или чтение байтов напрямую с помощью [`tokenize()`](https://python-all.ru/3.16/library/tokenize.html#tokenize.tokenize):238239```python240import tokenize241242with open('hello.py', 'rb') as f:243    tokens = tokenize.tokenize(f.readline)244    for token in tokens:245        print(token)246```247