Содержание страницы
tokenize – Токенизатор исходного кода Python¶tokenize – Tokenizer for Python source
Исходный код: Lib/tokenize.py
Модуль tokenize предоставляет лексический анализатор для исходного кода Python,
реализованный на Python. Анализатор в этом модуле также возвращает комментарии в виде токенов, что делает его полезным для реализации «pretty-printers», включая цветовые выделители для отображения на экране.
Чтобы упростить обработку потока токенов, все токены операторов и
разделителей, а также Ellipsis возвращаются с использованием
общего типа токена OP. Точный
tип можно определить, проверив свойство exact_type у
именованного кортежа, возвращаемого функцией tokenize.tokenize().
Предупреждение
Обратите внимание, что функции в этом модуле предназначены только для анализа
синтаксически корректного кода Python (кода, который не вызывает ошибок при разборе
с помощью ast.parse()). Поведение функций в этом модуле
не определено при передаче некорректного кода Python и может измениться в любой
момент.
Токенизация входных данных¶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
Использование командной строки¶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)