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

tokenize.md

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

1> **Источник:** https://python-all.ru/3.7/library/tokenize.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# [`tokenize`](https://python-all.ru/3.7/library/tokenize.html#module-tokenize) – Токенизатор исходного кода Python89**Исходный код:** [Lib/tokenize.py](https://python-all.ru/src/3.7/Lib/tokenize.py)1011---1213Модуль [`tokenize`](https://python-all.ru/3.7/library/tokenize.html#module-tokenize) предоставляет лексический анализатор для исходного кода Python, реализованный на Python. Анализатор в этом модуле также возвращает комментарии в виде токенов, что делает его полезным для реализации «pretty-printers», включая цветовые выделители для отображения на экране.1415Чтобы упростить обработку потока токенов, все токены [операторов](https://python-all.ru/3.7/reference/lexical_analysis.html#operators) и [разделителей](https://python-all.ru/3.7/reference/lexical_analysis.html#delimiters), а также [`Ellipsis`](https://python-all.ru/3.7/library/constants.html#Ellipsis) возвращаются с использованием общего типа токена [`OP`](https://python-all.ru/3.7/library/token.html#token.OP). Точный tип можно определить, проверив свойство `exact_type` у [именованного кортежа](https://python-all.ru/3.7/glossary.html#term-named-tuple), возвращаемого функцией [`tokenize.tokenize()`](https://python-all.ru/3.7/library/tokenize.html#tokenize.tokenize).1617## Токенизация входных данных1819Основной точкой входа является [генератор](https://python-all.ru/3.7/glossary.html#term-generator):2021#### `tokenize.tokenize(readline)`2223Генератор [`tokenize()`](https://python-all.ru/3.7/library/tokenize.html#tokenize.tokenize) требует один аргумент, *readline*, который должен быть вызываемым объектом, предоставляющим тот же интерфейс, что и метод [`io.IOBase.readline()`](https://python-all.ru/3.7/library/io.html#io.IOBase.readline) файловых объектов. Каждый вызов функции должен возвращать одну строку входных данных в виде байтов.2425Генератор создаёт 5-кортежи со следующими элементами: тип токена; строка токена; 2-кортеж `(srow, scol)` из целых чисел, задающих строку и столбец, где токен начинается в исходном коде; 2-кортеж `(erow, ecol)` из целых чисел, задающих строку и столбец, где токен заканчивается в исходном коде; и строка, в которой был найден токен. Передаваемая строка (последний элемент кортежа) – это *логическая* строка; строки продолжения включены. 5-кортеж возвращается как [именованный кортеж](https://python-all.ru/3.7/glossary.html#term-named-tuple) с именами полей: `type string start end line`.2627Возвращаемый [именованный кортеж](https://python-all.ru/3.7/glossary.html#term-named-tuple) имеет дополнительное свойство с именем `exact_type`, которое содержит точный тип оператора для токенов [`OP`](https://python-all.ru/3.7/library/token.html#token.OP). Для всех остальных типов токенов `exact_type` равно полю `type` именованного кортежа.2829Изменено в версии 3.1: Добавлена поддержка именованных кортежей.3031Изменено в версии 3.3: Добавлена поддержка `exact_type`.3233[`tokenize()`](https://python-all.ru/3.7/library/tokenize.html#tokenize.tokenize) определяет исходную кодировку файла, проверяя наличие UTF-8 BOM или кодировочной метки, в соответствии с [**PEP 263**](https://python-all.ru/3.7/library/tokenize.html).3435Все константы из модуля [`token`](https://python-all.ru/3.7/library/token.html#module-token) также экспортируются из [`tokenize`](https://python-all.ru/3.7/library/tokenize.html#module-tokenize).3637Предоставляется ещё одна функция для обращения процесса токенизации. Это полезно для создания инструментов, которые токенизируют скрипт, изменяют поток токенов и записывают изменённый скрипт обратно.3839#### `tokenize.untokenize(iterable)`4041Преобразует токены обратно в исходный код Python. *Итерируемый объект* должен возвращать последовательности как минимум из двух элементов: типа токена и строки токена. Все дополнительные элементы последовательности игнорируются.4243Восстановленный скрипт возвращается в виде одной строки. Результат гарантированно токенизируется обратно в соответствии с входными данными, что обеспечивает преобразование без потерь и полную обратимость. Гарантия распространяется только на тип токена и строку токена, поскольку расстояния между токенами (позиции столбцов) могут измениться.4445Он возвращает байты, закодированные с использованием токена [`ENCODING`](https://python-all.ru/3.7/library/token.html#token.ENCODING), который является первой последовательностью токенов, выданной [`tokenize()`](https://python-all.ru/3.7/library/tokenize.html#tokenize.tokenize).4647[`tokenize()`](https://python-all.ru/3.7/library/tokenize.html#tokenize.tokenize) необходимо определить кодировку исходных файлов, которые он токенизирует. Функция, которую он использует для этого, доступна:4849#### `tokenize.detect_encoding(readline)`5051Функция [`detect_encoding()`](https://python-all.ru/3.7/library/tokenize.html#tokenize.detect_encoding) используется для определения кодировки, которая должна использоваться для декодирования файла исходного кода Python. Она требует один аргумент, readline, так же, как генератор [`tokenize()`](https://python-all.ru/3.7/library/tokenize.html#tokenize.tokenize).5253Она вызовет readline максимум дважды и вернёт используемую кодировку (в виде строки) и список любых строк (не декодированных из байтов), которые она прочитала .5455Он определяет кодировку по наличию UTF-8 BOM или кодировочной метки, как указано в [**PEP 263**](https://python-all.ru/3.7/library/tokenize.html). Если присутствуют и BOM, и метка, но они не согласуются, будет возбуждено [`SyntaxError`](https://python-all.ru/3.7/library/exceptions.html#SyntaxError). Обратите внимание: если найден BOM, в качестве кодировки будет возвращена `'utf-8-sig'`.5657Если кодировка не указана, то будет возвращено значение по умолчанию `'utf-8'`.5859Используйте [`open()`](https://python-all.ru/3.7/library/tokenize.html#tokenize.open) для открытия файлов исходного кода Python: он использует [`detect_encoding()`](https://python-all.ru/3.7/library/tokenize.html#tokenize.detect_encoding) для определения кодировки файла.6061#### `tokenize.open(filename)`6263Открывает файл в режиме только для чтения, используя кодировку, определённую с помощью [`detect_encoding()`](https://python-all.ru/3.7/library/tokenize.html#tokenize.detect_encoding).6465Новое в версии 3.2.6667#### `exception tokenize.TokenError`6869Возникает, когда докстринг или выражение, которое может быть разбито на несколько строк, не завершено нигде в файле, например:7071```python72"""Beginning of73docstring74```7576или:7778```python79[1,80 2,81 382```8384Обратите внимание, что незакрытые строки в одинарных кавычках не вызывают возникновения ошибки. Они токенизируются как [`ERRORTOKEN`](https://python-all.ru/3.7/library/token.html#token.ERRORTOKEN), после чего следует токенизация их содержимого.8586## Использование командной строки8788Новое в версии 3.3.8990Модуль [`tokenize`](https://python-all.ru/3.7/library/tokenize.html#module-tokenize) может быть выполнен как скрипт из командной строки. Это просто:9192```sh93python -m tokenize [-e] [filename.py]94```9596Принимаются следующие опции:9798#### `-h, --help`99100показывает это справочное сообщение и завершает работу101102#### `-e, --exact`103104отображает имена токенов с использованием точного типа105106Если указан `filename.py`, его содержимое токенизируется в stdout. В противном случае токенизация выполняется из stdin.107108## Примеры109110Пример переписчика скриптов, преобразующего литералы чисел с плавающей запятой в объекты Decimal :111112```python113from tokenize import tokenize, untokenize, NUMBER, STRING, NAME, OP114from io import BytesIO115116def decistmt(s):117    """Заменяет значения float на Decimal.118119    >>> from decimal import Decimal120    >>> s = 'print(+21.3e-5*-.1234/81.7)'121    >>> decistmt(s)122    "print (+Decimal ('21.3e-5')*-Decimal ('.1234')/Decimal ('81.7'))"123124    Формат показателя степени наследуется от библиотеки C платформы.125    Известные случаи: "e-007" (Windows) и "e-07" (не Windows). Поскольку126    мы показываем только 12 цифр, а 13-я не близка к 5, остальная127    часть вывода должна быть независимой от платформы.128129    >>> exec(s)  #doctest: +ELLIPSIS130    -3.21716034272e-0...7131132    Результаты вычислений с Decimal должны быть одинаковыми на всех133    платформах.134135    >>> exec(decistmt(s))136    -3.217160342717258261933904529E-7137    """138    result = []139    g = tokenize(BytesIO(s.encode('utf-8')).readline)  # токенизировать строку140    for toknum, tokval, _, _, _ in g:141        if toknum == NUMBER and '.' in tokval:  # заменить токены NUMBER142            result.extend([143                (NAME, 'Decimal'),144                (OP, '('),145                (STRING, repr(tokval)),146                (OP, ')')147            ])148        else:149            result.append((toknum, tokval))150    return untokenize(result).decode('utf-8')151```152153Пример токенизации из командной строки. Скрипт:154155```python156def say_hello():157    print("Hello, World!")158159say_hello()160```161162будет токенизирован в следующий вывод, где первый столбец – это диапазон координат строки/столбца, где найден токен, второй столбец – имя токена, а последний столбец – значение токена (если есть)163164```console165$ python -m tokenize hello.py1660,0-0,0:            ENCODING       'utf-8'1671,0-1,3:            NAME           'def'1681,4-1,13:           NAME           'say_hello'1691,13-1,14:          OP             '('1701,14-1,15:          OP             ')'1711,15-1,16:          OP             ':'1721,16-1,17:          NEWLINE        '\n'1732,0-2,4:            INDENT         '    '1742,4-2,9:            NAME           'print'1752,9-2,10:           OP             '('1762,10-2,25:          STRING         '"Hello, World!"'1772,25-2,26:          OP             ')'1782,26-2,27:          NEWLINE        '\n'1793,0-3,1:            NL             '\n'1804,0-4,0:            DEDENT         ''1814,0-4,9:            NAME           'say_hello'1824,9-4,10:           OP             '('1834,10-4,11:          OP             ')'1844,11-4,12:          NEWLINE        '\n'1855,0-5,0:            ENDMARKER      ''186```187188Точные имена типов токенов можно отобразить с помощью опции [`-e`](https://python-all.ru/3.7/library/tokenize.html#cmdoption-tokenize-e):189190```console191$ python -m tokenize -e hello.py1920,0-0,0:            ENCODING       'utf-8'1931,0-1,3:            NAME           'def'1941,4-1,13:           NAME           'say_hello'1951,13-1,14:          LPAR           '('1961,14-1,15:          RPAR           ')'1971,15-1,16:          COLON          ':'1981,16-1,17:          NEWLINE        '\n'1992,0-2,4:            INDENT         '    '2002,4-2,9:            NAME           'print'2012,9-2,10:           LPAR           '('2022,10-2,25:          STRING         '"Hello, World!"'2032,25-2,26:          RPAR           ')'2042,26-2,27:          NEWLINE        '\n'2053,0-3,1:            NL             '\n'2064,0-4,0:            DEDENT         ''2074,0-4,9:            NAME           'say_hello'2084,9-4,10:           LPAR           '('2094,10-4,11:          RPAR           ')'2104,11-4,12:          NEWLINE        '\n'2115,0-5,0:            ENDMARKER      ''212```213214Пример программной токенизации файла: чтение строк Unicode вместо байтов с помощью `generate_tokens()`:215216```python217import tokenize218219with tokenize.open('hello.py') as f:220    tokens = tokenize.generate_tokens(f.readline)221    for token in tokens:222        print(token)223```224225Или чтение байтов напрямую с помощью [`tokenize()`](https://python-all.ru/3.7/library/tokenize.html#tokenize.tokenize):226227```python228import tokenize229230with open('hello.py', 'rb') as f:231    tokens = tokenize.tokenize(f.readline)232    for token in tokens:233        print(token)234```235