tokenize – токенизатор исходного кода Python¶tokenize – Tokenizer for Python source
Модуль tokenize предоставляет лексический сканер для исходного кода Python, реализованный на Python. Сканер в этом модуле также возвращает комментарии как токены, что позволяет использовать его для реализации «pretty-printers», включая цветовые подсветки для экранных дисплеев.
Основной точкой входа является генератор:
- tokenize.tokenize(readline)¶
Генератор tokenize() требует один аргумент, readline, который должен быть вызываемым объектом с тем же интерфейсом, что и метод readline() встроенных файловых объектов (см. раздел Файловые объекты). Каждый вызов функции должен возвращать одну строку ввода в виде байтов.
Генератор выдаёт кортежи из 5 элементов: тип токена; строка токена; кортеж из двух целых чисел (srow, scol), задающий строку и столбец начала токена в исходнике; кортеж из двух целых чисел (erow, ecol), задающий строку и столбец конца токена; и строка, в которой был найден токен. Передаваемая строка (последний элемент кортежа) – это логическая строка; строки продолжения включаются.
tokenize() определяет кодировку исходного файла, ища BOM UTF-8 или cookie кодировки, в соответствии с PEP 263.
Все константы из модуля token также экспортируются из tokenize, как и три дополнительных значения типа токена:
- tokenize.COMMENT¶
- Значение токена, используемое для обозначения комментария.
- tokenize.NL¶
- Значение токена, используемое для обозначения незавершающего перевода строки. Токен NEWLINE обозначает конец логической строки кода Python; токены NL создаются, когда логическая строка кода продолжается на нескольких физических строках.
- tokenize.ENCODING¶
- Значение токена, указывающее кодировку, используемую для декодирования исходных байтов в текст. Первый токен, возвращаемый tokenize(), всегда будет токеном ENCODING.
Предоставляется ещё одна функция для обращения процесса токенизации. Это полезно для создания инструментов, которые токенизируют скрипт, изменяют поток токенов и записывают изменённый скрипт обратно.
- tokenize.untokenize(iterable)¶
Преобразует токены обратно в исходный код Python. Итерируемый объект должен возвращать последовательности как минимум из двух элементов: типа токена и строки токена. Все дополнительные элементы последовательности игнорируются.
Восстановленный скрипт возвращается в виде одной строки. Результат гарантированно токенизируется обратно в соответствии с входными данными, что обеспечивает преобразование без потерь и полную обратимость. Гарантия распространяется только на тип токена и строку токена, поскольку расстояния между токенами (позиции столбцов) могут измениться.
Он возвращает байты, закодированные с использованием токена ENCODING, который является первой последовательностью токенов, выводимой tokenize().
tokenize() необходимо определять кодировку исходных файлов, которые он токенизирует. Функция, которую он для этого использует, доступна:
- tokenize.detect_encoding(readline)¶
The detect_encoding() function is used to detect the encoding that should be used to decode a Python source file. It requires one argment, readline, in the same way as the tokenize() generator.
Она вызовет readline максимум дважды и вернёт используемую кодировку (в виде строки) и список любых строк (не декодированных из байтов), которые она прочитала .
Она определяет кодировку по наличию метки BOM UTF-8 или cookie кодировки, как указано в PEP 0263. Если присутствуют и BOM, и cookie, но они не совпадают, будет возбуждено исключение SyntaxError.
Если кодировка не указана, будет возвращена кодировка по умолчанию – 'utf-8'.
Пример перезаписывателя скриптов, преобразующего литералы с плавающей запятой в объекты Decimal:
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')