tokenize.md
1> **Источник:** https://python-all.ru/3.1/library/tokenize.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# 30.7. `tokenize` – токенизатор исходного кода Python89Модуль `tokenize` предоставляет лексический сканер для исходного кода Python, реализованный на Python. Сканер в этом модуле также возвращает комментарии как токены, что позволяет использовать его для реализации «pretty-printers», включая цветовые подсветки для экранных дисплеев.1011Основной точкой входа является [*генератор*](https://python-all.ru/3.1/glossary.html#term-generator):1213#### `tokenize.tokenize(readline)`1415Генератор [`tokenize()`](https://python-all.ru/3.1/library/tokenize.html#tokenize.tokenize) требует один аргумент, *readline*, который должен быть вызываемым объектом, предоставляющим тот же интерфейс, что и метод [`io.IOBase.readline()`](https://python-all.ru/3.1/library/io.html#io.IOBase.readline) файловых объектов. Каждый вызов функции должен возвращать одну строку ввода в виде байтов.1617Генератор выдает 5-кортежи со следующими элементами: тип токена; строка токена; 2-кортеж `(srow, scol)` из целых чисел, указывающих строку и столбец начала токена в исходном коде; 2-кортеж `(erow, ecol)` из целых чисел, указывающих строку и столбец конца токена в исходном коде; и строку, в которой был найден токен. Передаваемая строка (последний элемент кортежа) является *логической* строкой; строки продолжения включены. 5-кортеж возвращается как [*именованный кортеж*](https://python-all.ru/3.1/glossary.html#term-named-tuple) с именами полей: `type string start end line`.1819Изменено в версии 3.1: Добавлена поддержка именованных кортежей.2021[`tokenize()`](https://python-all.ru/3.1/library/tokenize.html#tokenize.tokenize) определяет кодировку исходного файла, ища BOM UTF-8 или cookie кодировки, в соответствии с [**PEP 263**](https://python-all.ru/3.1/library/tokenize.html).2223Все константы из модуля [`token`](https://python-all.ru/3.1/library/token.html#module-token) также экспортируются из `tokenize`, как и три дополнительных значения типа токена:2425#### `tokenize.COMMENT`2627Значение токена, используемое для обозначения комментария.2829#### `tokenize.NL`3031Значение токена, используемое для обозначения незавершающего перевода строки. Токен NEWLINE обозначает конец логической строки кода Python; токены NL создаются, когда логическая строка кода продолжается на нескольких физических строках.3233#### `tokenize.ENCODING`3435Значение токена, указывающее кодировку, используемую для декодирования исходных байтов в текст. Первый токен, возвращаемый3637[`tokenize()`](https://python-all.ru/3.1/library/tokenize.html#tokenize.tokenize)3839, всегда будет токеном ENCODING.4041Предоставляется ещё одна функция для обращения процесса токенизации. Это полезно для создания инструментов, которые токенизируют скрипт, изменяют поток токенов и записывают изменённый скрипт обратно.4243#### `tokenize.untokenize(iterable)`4445Преобразует токены обратно в исходный код Python. *Итерируемый объект* должен возвращать последовательности как минимум из двух элементов: типа токена и строки токена. Все дополнительные элементы последовательности игнорируются.4647Восстановленный скрипт возвращается в виде одной строки. Результат гарантированно токенизируется обратно в соответствии с входными данными, что обеспечивает преобразование без потерь и полную обратимость. Гарантия распространяется только на тип токена и строку токена, поскольку расстояния между токенами (позиции столбцов) могут измениться.4849Он возвращает байты, закодированные с использованием токена ENCODING, который является первой последовательностью токенов, выводимой [`tokenize()`](https://python-all.ru/3.1/library/tokenize.html#tokenize.tokenize).5051[`tokenize()`](https://python-all.ru/3.1/library/tokenize.html#tokenize.tokenize) необходимо определять кодировку исходных файлов, которые он токенизирует. Функция, которую он для этого использует, доступна:5253#### `tokenize.detect_encoding(readline)`5455Функция [`detect_encoding()`](https://python-all.ru/3.1/library/tokenize.html#tokenize.detect_encoding) используется для определения кодировки, которая должна использоваться для декодирования исходного файла Python. Она требует один аргумент, readline, так же, как и генератор [`tokenize()`](https://python-all.ru/3.1/library/tokenize.html#tokenize.tokenize).5657Она вызовет readline максимум дважды и вернёт используемую кодировку (в виде строки) и список любых строк (не декодированных из байтов), которые она прочитала .5859Он определяет кодировку по наличию UTF-8 BOM или cookie кодировки, как указано в [**PEP 263**](https://python-all.ru/3.1/library/tokenize.html). Если присутствуют и BOM, и cookie, но они не согласуются, будет вызвано исключение SyntaxError.6061Если кодировка не указана, то будет возвращено значение по умолчанию `'utf-8'`.6263Пример перезаписывателя скриптов, преобразующего литералы с плавающей запятой в объекты Decimal:6465```python66from tokenize import tokenize, untokenize, NUMBER, STRING, NAME, OP67from io import BytesIO6869def decistmt(s):70 """Заменяет значения float на Decimal.7172 >>> from decimal import Decimal73 >>> s = 'print(+21.3e-5*-.1234/81.7)'74 >>> decistmt(s)75 "print (+Decimal ('21.3e-5')*-Decimal ('.1234')/Decimal ('81.7'))"7677 Формат показателя степени наследуется от библиотеки C платформы.78 Известные случаи: "e-007" (Windows) и "e-07" (не Windows). Поскольку79 мы показываем только 12 цифр, а 13-я не близка к 5, остальная80 часть вывода должна быть независимой от платформы.8182 >>> exec(s) #doctest: +ELLIPSIS83 -3.21716034272e-0...78485 Результаты вычислений с Decimal должны быть одинаковыми на всех86 платформах.8788 >>> exec(decistmt(s))89 -3.217160342717258261933904529E-790 """91 result = []92 g = tokenize(BytesIO(s.encode('utf-8')).readline) # токенизировать строку93 for toknum, tokval, _, _, _ in g:94 if toknum == NUMBER and '.' in tokval: # заменить токены NUMBER95 result.extend([96 (NAME, 'Decimal'),97 (OP, '('),98 (STRING, repr(tokval)),99 (OP, ')')100 ])101 else:102 result.append((toknum, tokval))103 return untokenize(result).decode('utf-8')104```105