Содержание страницы
tokenize – Токенизатор исходного кода Python¶tokenize – Tokenizer for Python source
Исходный код: Lib/tokenize.py
Модуль tokenize предоставляет лексический анализатор для исходного кода Python,
реализованный на Python. Анализатор в этом модуле также возвращает комментарии в виде токенов, что делает его полезным для реализации «pretty-printers», включая цветовые выделители для отображения на экране.
Чтобы упростить обработку потока токенов, все токены операторов и
разделителей, а также Ellipsis возвращаются с использованием
общего типа токена OP. Точный
tип можно определить, проверив свойство exact_type у
именованного кортежа, возвращаемого функцией tokenize.tokenize().
Токенизация входных данных¶Tokenizing Input
Основной точкой входа является генератор:
-
tokenize.tokenize(readline)¶ Генератор
tokenize()требует один аргумент, readline, который должен быть вызываемым объектом, предоставляющим тот же интерфейс, что и методio.IOBase.readline()файловых объектов. Каждый вызов функции должен возвращать одну строку входных данных в виде байтов.Генератор создаёт 5-кортежи со следующими элементами: тип токена; строка токена; 2-кортеж
(srow, scol)из целых чисел, указывающих строку и столбец, где токен начинается в исходном коде; 2-кортеж(erow, ecol)из целых чисел, указывающих строку и столбец, где токен заканчивается; и строка, в которой был найден токен. Передаваемая строка (последний элемент кортежа) является физической строкой. 5-кортеж возвращается в виде именованного кортежа с именами полей:type string start end line.Возвращаемый именованный кортеж имеет дополнительное свойство с именем
exact_type, которое содержит точный тип оператора для токеновOP. Для всех остальных типов токеновexact_typeравно полюtypeименованного кортежа.Изменено в версии 3.1: Добавлена поддержка именованных кортежей.
Изменено в версии 3.3: Добавлена поддержка
exact_type.tokenize()определяет исходную кодировку файла, проверяя наличие UTF-8 BOM или кодировочной метки, в соответствии с PEP 263.
-
tokenize.generate_tokens(readline)¶ Токенизирует исходный код, читая строки Unicode вместо байтов.
Как и
tokenize(), аргумент readline является вызываемым объектом, возвращающим одну строку входных данных. Однакоgenerate_tokens()ожидает, что readline будет возвращать объект str, а не bytes.Результатом является итератор, возвращающий именованные кортежи, точно как
tokenize(). Он не возвращает токенENCODING.
Все константы из модуля token также экспортируются из tokenize.
Предоставляется ещё одна функция для обращения процесса токенизации. Это полезно для создания инструментов, которые токенизируют скрипт, изменяют поток токенов и записывают изменённый скрипт обратно.
-
tokenize.untokenize(iterable)¶ Преобразует токены обратно в исходный код Python. Итерируемый объект должен возвращать последовательности как минимум из двух элементов: типа токена и строки токена. Все дополнительные элементы последовательности игнорируются.
Восстановленный скрипт возвращается в виде одной строки. Результат гарантированно токенизируется обратно в соответствии с входными данными, что обеспечивает преобразование без потерь и полную обратимость. Гарантия распространяется только на тип токена и строку токена, поскольку расстояния между токенами (позиции столбцов) могут измениться.
Он возвращает байты, закодированные с использованием токена
ENCODING, который является первым токеном последовательности, выводимойtokenize(). Если во входных данных нет токена кодировки, вместо этого возвращается str.
tokenize() необходимо определить кодировку исходных файлов, которые он токенизирует. Функция,
которую он использует для этого, доступна:
-
tokenize.detect_encoding(readline)¶ Функция
detect_encoding()используется для определения кодировки, которая должна использоваться для декодирования файла исходного кода Python. Она требует один аргумент, readline, так же, как генераторtokenize().Она вызовет readline максимум дважды и вернёт используемую кодировку (в виде строки) и список любых строк (не декодированных из байтов), которые она прочитала .
Он определяет кодировку по наличию UTF-8 BOM или кодировочной метки, как указано в PEP 263. Если присутствуют и BOM, и метка, но они не согласуются, будет возбуждено
SyntaxError. Обратите внимание: если найден BOM, в качестве кодировки будет возвращена'utf-8-sig'.Если кодировка не указана, то будет возвращено значение по умолчанию
'utf-8'.Используйте
open()для открытия файлов исходного кода Python: он используетdetect_encoding()для определения кодировки файла.
-
tokenize.open(filename)¶ Открывает файл в режиме только для чтения, используя кодировку, определённую с помощью
detect_encoding().Новое в версии 3.2.
-
exception
tokenize.TokenError¶ Возникает, когда докстринг или выражение, которое может быть разбито на несколько строк, не завершено нигде в файле, например:
"""Beginning of docstring
или:
[1, 2, 3
Обратите внимание, что незакрытые строки в одинарных кавычках не вызывают возникновения
ошибки. Они токенизируются как ERRORTOKEN, после чего следует
токенизация их содержимого.
Использование командной строки¶Command-Line Usage
Новое в версии 3.3.
Модуль tokenize может быть выполнен как скрипт из командной строки. Это просто:
python -m tokenize [-e] [filename.py]
Принимаются следующие опции:
-
-h,--help¶ показывает это справочное сообщение и завершает работу
-
-e,--exact¶ отображает имена токенов с использованием точного типа
Если указан filename.py, его содержимое токенизируется в stdout.
В противном случае токенизация выполняется из stdin.
Примеры¶Examples
Пример переписчика скриптов, преобразующего литералы чисел с плавающей запятой в объекты Decimal :
from tokenize import tokenize, untokenize, NUMBER, STRING, NAME, OP
from io import BytesIO
def decistmt(s):
"""Заменяет значения float на Decimal.
>>> from decimal import Decimal
>>> s = 'print(+21.3e-5*-.1234/81.7)'
>>> decistmt(s)
"print (+Decimal ('21.3e-5')*-Decimal ('.1234')/Decimal ('81.7'))"
Формат показателя степени наследуется от библиотеки C платформы.
Известные случаи: "e-007" (Windows) и "e-07" (не Windows). Поскольку
мы показываем только 12 цифр, а 13-я не близка к 5, остальная
часть вывода должна быть независимой от платформы.
>>> exec(s) #doctest: +ELLIPSIS
-3.21716034272e-0...7
Результаты вычислений с Decimal должны быть одинаковыми на всех
платформах.
>>> exec(decistmt(s))
-3.217160342717258261933904529E-7
"""
result = []
g = tokenize(BytesIO(s.encode('utf-8')).readline) # токенизировать строку
for toknum, tokval, _, _, _ in g:
if toknum == NUMBER and '.' in tokval: # заменить токены NUMBER
result.extend([
(NAME, 'Decimal'),
(OP, '('),
(STRING, repr(tokval)),
(OP, ')')
])
else:
result.append((toknum, tokval))
return untokenize(result).decode('utf-8')
Пример токенизации из командной строки. Скрипт:
def say_hello():
print("Hello, World!")
say_hello()
будет токенизирован в следующий вывод, где первый столбец – это диапазон координат строки/столбца, где найден токен, второй столбец – имя токена, а последний столбец – значение токена (если есть)
$ python -m tokenize hello.py
0,0-0,0: ENCODING 'utf-8'
1,0-1,3: NAME 'def'
1,4-1,13: NAME 'say_hello'
1,13-1,14: OP '('
1,14-1,15: OP ')'
1,15-1,16: OP ':'
1,16-1,17: NEWLINE '\n'
2,0-2,4: INDENT ' '
2,4-2,9: NAME 'print'
2,9-2,10: OP '('
2,10-2,25: STRING '"Hello, World!"'
2,25-2,26: OP ')'
2,26-2,27: NEWLINE '\n'
3,0-3,1: NL '\n'
4,0-4,0: DEDENT ''
4,0-4,9: NAME 'say_hello'
4,9-4,10: OP '('
4,10-4,11: OP ')'
4,11-4,12: NEWLINE '\n'
5,0-5,0: ENDMARKER ''
Точные имена типов токенов можно отобразить с помощью опции -e:
$ python -m tokenize -e hello.py
0,0-0,0: ENCODING 'utf-8'
1,0-1,3: NAME 'def'
1,4-1,13: NAME 'say_hello'
1,13-1,14: LPAR '('
1,14-1,15: RPAR ')'
1,15-1,16: COLON ':'
1,16-1,17: NEWLINE '\n'
2,0-2,4: INDENT ' '
2,4-2,9: NAME 'print'
2,9-2,10: LPAR '('
2,10-2,25: STRING '"Hello, World!"'
2,25-2,26: RPAR ')'
2,26-2,27: NEWLINE '\n'
3,0-3,1: NL '\n'
4,0-4,0: DEDENT ''
4,0-4,9: NAME 'say_hello'
4,9-4,10: LPAR '('
4,10-4,11: RPAR ')'
4,11-4,12: NEWLINE '\n'
5,0-5,0: ENDMARKER ''
Пример программной токенизации файла: чтение строк Unicode
вместо байтов с помощью generate_tokens():
import tokenize
with tokenize.open('hello.py') as f:
tokens = tokenize.generate_tokens(f.readline)
for token in tokens:
print(token)
Или чтение байтов напрямую с помощью tokenize():
import tokenize
with open('hello.py', 'rb') as f:
tokens = tokenize.tokenize(f.readline)
for token in tokens:
print(token)