tokenize.md
1> **Источник:** https://python-all.ru/3.9/library/tokenize.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# [`tokenize`](https://python-all.ru/3.9/library/tokenize.html#module-tokenize) – Токенизатор исходного кода Python89**Исходный код:** [Lib/tokenize.py](https://python-all.ru/src/3.9/Lib/tokenize.py)1011---1213Модуль [`tokenize`](https://python-all.ru/3.9/library/tokenize.html#module-tokenize) предоставляет лексический анализатор для исходного кода Python, реализованный на Python. Анализатор в этом модуле также возвращает комментарии в виде токенов, что делает его полезным для реализации «pretty-printers», включая цветовые выделители для отображения на экране.1415Чтобы упростить обработку потока токенов, все токены [операторов](https://python-all.ru/3.9/reference/lexical_analysis.html#operators) и [разделителей](https://python-all.ru/3.9/reference/lexical_analysis.html#delimiters), а также [`Ellipsis`](https://python-all.ru/3.9/library/constants.html#Ellipsis) возвращаются с использованием общего типа токена [`OP`](https://python-all.ru/3.9/library/token.html#token.OP). Точный tип можно определить, проверив свойство `exact_type` у [именованного кортежа](https://python-all.ru/3.9/glossary.html#term-named-tuple), возвращаемого функцией [`tokenize.tokenize()`](https://python-all.ru/3.9/library/tokenize.html#tokenize.tokenize).1617## Токенизация входных данных1819Основной точкой входа является [генератор](https://python-all.ru/3.9/glossary.html#term-generator):2021#### `tokenize.tokenize(readline)`2223Генератор [`tokenize()`](https://python-all.ru/3.9/library/tokenize.html#tokenize.tokenize) требует один аргумент, *readline*, который должен быть вызываемым объектом, предоставляющим тот же интерфейс, что и метод [`io.IOBase.readline()`](https://python-all.ru/3.9/library/io.html#io.IOBase.readline) файловых объектов. Каждый вызов функции должен возвращать одну строку входных данных в виде байтов.2425Генератор создаёт 5-кортежи со следующими элементами: тип токена; строка токена; 2-кортеж `(srow, scol)` из целых чисел, указывающих строку и столбец, где токен начинается в исходном коде; 2-кортеж `(erow, ecol)` из целых чисел, указывающих строку и столбец, где токен заканчивается; и строка, в которой был найден токен. Передаваемая строка (последний элемент кортежа) является *физической* строкой. 5-кортеж возвращается в виде [именованного кортежа](https://python-all.ru/3.9/glossary.html#term-named-tuple) с именами полей: `type string start end line`.2627Возвращаемый [именованный кортеж](https://python-all.ru/3.9/glossary.html#term-named-tuple) имеет дополнительное свойство с именем `exact_type`, которое содержит точный тип оператора для токенов [`OP`](https://python-all.ru/3.9/library/token.html#token.OP). Для всех остальных типов токенов `exact_type` равно полю `type` именованного кортежа.2829Изменено в версии 3.1: Добавлена поддержка именованных кортежей.3031Изменено в версии 3.3: Добавлена поддержка `exact_type`.3233[`tokenize()`](https://python-all.ru/3.9/library/tokenize.html#tokenize.tokenize) определяет исходную кодировку файла, проверяя наличие UTF-8 BOM или кодировочной метки, в соответствии с [**PEP 263**](https://python-all.ru/3.9/library/tokenize.html).3435#### `tokenize.generate_tokens(readline)`3637Токенизирует исходный код, читая строки Unicode вместо байтов.3839Как и [`tokenize()`](https://python-all.ru/3.9/library/tokenize.html#tokenize.tokenize), аргумент *readline* является вызываемым объектом, возвращающим одну строку входных данных. Однако [`generate_tokens()`](https://python-all.ru/3.9/library/tokenize.html#tokenize.generate_tokens) ожидает, что *readline* будет возвращать объект str, а не bytes.4041Результатом является итератор, возвращающий именованные кортежи, точно как [`tokenize()`](https://python-all.ru/3.9/library/tokenize.html#tokenize.tokenize). Он не возвращает токен [`ENCODING`](https://python-all.ru/3.9/library/token.html#token.ENCODING).4243Все константы из модуля [`token`](https://python-all.ru/3.9/library/token.html#module-token) также экспортируются из [`tokenize`](https://python-all.ru/3.9/library/tokenize.html#module-tokenize).4445Предоставляется ещё одна функция для обращения процесса токенизации. Это полезно для создания инструментов, которые токенизируют скрипт, изменяют поток токенов и записывают изменённый скрипт обратно.4647#### `tokenize.untokenize(iterable)`4849Преобразует токены обратно в исходный код Python. *Итерируемый объект* должен возвращать последовательности как минимум из двух элементов: типа токена и строки токена. Все дополнительные элементы последовательности игнорируются.5051Восстановленный скрипт возвращается в виде одной строки. Результат гарантированно токенизируется обратно в соответствии с входными данными, что обеспечивает преобразование без потерь и полную обратимость. Гарантия распространяется только на тип токена и строку токена, поскольку расстояния между токенами (позиции столбцов) могут измениться.5253Он возвращает байты, закодированные с использованием токена [`ENCODING`](https://python-all.ru/3.9/library/token.html#token.ENCODING), который является первым токеном последовательности, выводимой [`tokenize()`](https://python-all.ru/3.9/library/tokenize.html#tokenize.tokenize). Если во входных данных нет токена кодировки, вместо этого возвращается str.5455[`tokenize()`](https://python-all.ru/3.9/library/tokenize.html#tokenize.tokenize) необходимо определить кодировку исходных файлов, которые он токенизирует. Функция, которую он использует для этого, доступна:5657#### `tokenize.detect_encoding(readline)`5859Функция [`detect_encoding()`](https://python-all.ru/3.9/library/tokenize.html#tokenize.detect_encoding) используется для определения кодировки, которая должна использоваться для декодирования файла исходного кода Python. Она требует один аргумент, readline, так же, как генератор [`tokenize()`](https://python-all.ru/3.9/library/tokenize.html#tokenize.tokenize).6061Она вызовет readline максимум дважды и вернёт используемую кодировку (в виде строки) и список любых строк (не декодированных из байтов), которые она прочитала .6263Он определяет кодировку по наличию UTF-8 BOM или кодировочной метки, как указано в [**PEP 263**](https://python-all.ru/3.9/library/tokenize.html). Если присутствуют и BOM, и метка, но они не согласуются, будет возбуждено [`SyntaxError`](https://python-all.ru/3.9/library/exceptions.html#SyntaxError). Обратите внимание: если найден BOM, в качестве кодировки будет возвращена `'utf-8-sig'`.6465Если кодировка не указана, то будет возвращено значение по умолчанию `'utf-8'`.6667Используйте [`open()`](https://python-all.ru/3.9/library/tokenize.html#tokenize.open) для открытия файлов исходного кода Python: он использует [`detect_encoding()`](https://python-all.ru/3.9/library/tokenize.html#tokenize.detect_encoding) для определения кодировки файла.6869#### `tokenize.open(filename)`7071Открывает файл в режиме только для чтения, используя кодировку, определённую с помощью [`detect_encoding()`](https://python-all.ru/3.9/library/tokenize.html#tokenize.detect_encoding).7273Новое в версии 3.2.7475#### `exception tokenize.TokenError`7677Возникает, когда докстринг или выражение, которое может быть разбито на несколько строк, не завершено нигде в файле, например:7879```python80"""Beginning of81docstring82```8384или:8586```python87[1,88 2,89 390```9192Обратите внимание, что незакрытые строки в одинарных кавычках не вызывают возникновения ошибки. Они токенизируются как [`ERRORTOKEN`](https://python-all.ru/3.9/library/token.html#token.ERRORTOKEN), после чего следует токенизация их содержимого.9394## Использование командной строки9596Новое в версии 3.3.9798Модуль [`tokenize`](https://python-all.ru/3.9/library/tokenize.html#module-tokenize) может быть выполнен как скрипт из командной строки. Это просто:99100```sh101python -m tokenize [-e] [filename.py]102```103104Принимаются следующие опции:105106#### `-h, --help`107108показывает это справочное сообщение и завершает работу109110#### `-e, --exact`111112отображает имена токенов с использованием точного типа113114Если указан `filename.py`, его содержимое токенизируется в stdout. В противном случае токенизация выполняется из stdin.115116## Примеры117118Пример переписчика скриптов, преобразующего литералы чисел с плавающей запятой в объекты Decimal :119120```python121from tokenize import tokenize, untokenize, NUMBER, STRING, NAME, OP122from io import BytesIO123124def decistmt(s):125 """Заменяет значения float на Decimal.126127 >>> from decimal import Decimal128 >>> s = 'print(+21.3e-5*-.1234/81.7)'129 >>> decistmt(s)130 "print (+Decimal ('21.3e-5')*-Decimal ('.1234')/Decimal ('81.7'))"131132 Формат показателя степени наследуется от библиотеки C платформы.133 Известные случаи: "e-007" (Windows) и "e-07" (не Windows). Поскольку134 мы показываем только 12 цифр, а 13-я не близка к 5, остальная135 часть вывода должна быть независимой от платформы.136137 >>> exec(s) #doctest: +ELLIPSIS138 -3.21716034272e-0...7139140 Результаты вычислений с Decimal должны быть одинаковыми на всех141 платформах.142143 >>> exec(decistmt(s))144 -3.217160342717258261933904529E-7145 """146 result = []147 g = tokenize(BytesIO(s.encode('utf-8')).readline) # токенизировать строку148 for toknum, tokval, _, _, _ in g:149 if toknum == NUMBER and '.' in tokval: # заменить токены NUMBER150 result.extend([151 (NAME, 'Decimal'),152 (OP, '('),153 (STRING, repr(tokval)),154 (OP, ')')155 ])156 else:157 result.append((toknum, tokval))158 return untokenize(result).decode('utf-8')159```160161Пример токенизации из командной строки. Скрипт:162163```python164def say_hello():165 print("Hello, World!")166167say_hello()168```169170будет токенизирован в следующий вывод, где первый столбец – это диапазон координат строки/столбца, где найден токен, второй столбец – имя токена, а последний столбец – значение токена (если есть)171172```console173$ python -m tokenize hello.py1740,0-0,0: ENCODING 'utf-8'1751,0-1,3: NAME 'def'1761,4-1,13: NAME 'say_hello'1771,13-1,14: OP '('1781,14-1,15: OP ')'1791,15-1,16: OP ':'1801,16-1,17: NEWLINE '\n'1812,0-2,4: INDENT ' '1822,4-2,9: NAME 'print'1832,9-2,10: OP '('1842,10-2,25: STRING '"Hello, World!"'1852,25-2,26: OP ')'1862,26-2,27: NEWLINE '\n'1873,0-3,1: NL '\n'1884,0-4,0: DEDENT ''1894,0-4,9: NAME 'say_hello'1904,9-4,10: OP '('1914,10-4,11: OP ')'1924,11-4,12: NEWLINE '\n'1935,0-5,0: ENDMARKER ''194```195196Точные имена типов токенов можно отобразить с помощью опции [`-e`](https://python-all.ru/3.9/library/tokenize.html#cmdoption-tokenize-e):197198```console199$ python -m tokenize -e hello.py2000,0-0,0: ENCODING 'utf-8'2011,0-1,3: NAME 'def'2021,4-1,13: NAME 'say_hello'2031,13-1,14: LPAR '('2041,14-1,15: RPAR ')'2051,15-1,16: COLON ':'2061,16-1,17: NEWLINE '\n'2072,0-2,4: INDENT ' '2082,4-2,9: NAME 'print'2092,9-2,10: LPAR '('2102,10-2,25: STRING '"Hello, World!"'2112,25-2,26: RPAR ')'2122,26-2,27: NEWLINE '\n'2133,0-3,1: NL '\n'2144,0-4,0: DEDENT ''2154,0-4,9: NAME 'say_hello'2164,9-4,10: LPAR '('2174,10-4,11: RPAR ')'2184,11-4,12: NEWLINE '\n'2195,0-5,0: ENDMARKER ''220```221222Пример программной токенизации файла: чтение строк Unicode вместо байтов с помощью [`generate_tokens()`](https://python-all.ru/3.9/library/tokenize.html#tokenize.generate_tokens):223224```python225import tokenize226227with tokenize.open('hello.py') as f:228 tokens = tokenize.generate_tokens(f.readline)229 for token in tokens:230 print(token)231```232233Или чтение байтов напрямую с помощью [`tokenize()`](https://python-all.ru/3.9/library/tokenize.html#tokenize.tokenize):234235```python236import tokenize237238with open('hello.py', 'rb') as f:239 tokens = tokenize.tokenize(f.readline)240 for token in tokens:241 print(token)242```243