tokenize
— Токенизатор для исходного кода Python¶
Исходный код: Lib/tokenize.py
Модуль tokenize
предоставляет лексический сканер для исходного кода
Python , реализованного в Python. Сканер в этом модуле также возвращает
комментарии в качестве маркеров, что делает его полезным для реализации
«красивых принтов», включая краски для экранных дисплеев.
Чтобы упростить символическую обработку потока, весь оператор, символы
делимитера и Ellipsis
- возвращенный, используя универсальный символический тип
OP
. Точный тип можно определить, проверив свойство exact_type
на
именованный кортеж возвращенный из tokenize.tokenize()
.
Токенизация входа¶
Основной точкой входа является генератором:
-
tokenize.
tokenize
(readline)¶ Для
tokenize()
генератор требуется один аргумент readline, который должен быть вызываемым объектом, обеспечивающим тот же интерфейс, что и для методаio.IOBase.readline()
файловых объектов. Каждый вызов функции должен возвращает одну строку ввода в байтах.Генератор производит 5-кортежи с этими членами: тип токена; строка маркера; 2-кортежный
(srow, scol)
ints, указывающий строку и столбец, где начинается маркер в источнике; 2-кортежный(erow, ecol)
ints, указывающий строку и столбец, где маркер заканчивается в источнике; и строку, на которой был найден маркер. Переданная строка (последний элемент кортежа) - это физическая строка. 5 кортеж возвращенный как именованный кортеж с именами полей:type string start end line
.У возвращенный именованный кортеж есть дополнительное свойство с именем
exact_type
, содержащее точный тип оператора для маркеровOP
. Для всех остальных типов маркеровexact_type
равно именованному полюtype
кортежа.Изменено в версии 3.1: Добавлена поддержка именованных кортежей.
Изменено в версии 3.3: Добавлена поддержка
exact_type
.tokenize()
определяет источник кодировка файла, ища BOM UTF-8 или печенье кодировки, согласно PEP 263.
-
tokenize.
generate_tokens
(readline)¶ Маркировать исходный строки Юникода вместо байтов.
Как и
tokenize()
, аргумент readline является вызываемым, возвращающим одну строку ввода. Однакоgenerate_tokens()
ожидает, что readline возвращает объект str, а не байты.В результате получается итератор, дающий именованные кортежи, точно как
tokenize()
. Он не yield токенENCODING
.
Все константы из модуля token
также экспортируются из tokenize
.
Предусмотрена еще одна функция для обращения процесса токенизации. Это полезно для создания инструментов для токенизации сценария, изменения потока маркеров и обратной записи измененного сценария.
-
tokenize.
untokenize
(iterable)¶ Преобразует маркеры обратно в исходный код Python. В iterable должны возвращает последовательности, содержащие по крайней мере два элемента, тип маркера и строка маркера. Любые дополнительные элементы последовательности игнорируются.
Реконструированный сценарий возвращенный как единый строка. Результат гарантированно получает токенизацию для соответствия входному сигналу, так что преобразование происходит без потерь и обеспечивается передача в оба конца. Гарантия применяется только к типу маркера и маркеру строка так как интервал между маркерами (позициями столбцов) может измениться.
Он возвращает байты, кодированный используя токен
ENCODING
, который является первой последовательностью токенов, выводимойtokenize()
. Если во входном файле нет маркера кодировка, он возвращает str.
tokenize()
должен определить кодировку исходных файлов, которые он маркирует.
Функция, используемая для этого, доступна:
-
tokenize.
detect_encoding
(readline)¶ Функция
detect_encoding()
используемый для обнаружения кодировка, которые должны быть используемый для декодирования исходного файла Python. Он требует одного аргумента, readline, так же, как иtokenize()
генератор.Он вызовет readline максимум два раза, и возвращает кодировка используемый (как строка) и список любых строк (не декодированных из байтов), которые он прочитал.
Это обнаруживает кодировка от присутствия BOM UTF-8 или печенья кодировка, как определено в PEP 263. Если и спецификация, и cookie присутствуют, но не согласны,
SyntaxError
будет поднят. Обратите внимание, что при обнаружении спецификации'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
, после чего происходит
токенизация их содержимого.
Использование командной строки¶
Добавлено в версии 3.3.
Модуль tokenize
может быть выполнен в виде сценария из командной строки. Это
так же просто, как:
python -m tokenize [-e] [filename.py]
Принимаются следующие опции:
-
-h
,
--help
¶
показать это сообщение справки и выйти
-
-e
,
--exact
¶
отображение имен маркеров с использованием точного типа
Если указано filename.py
, его содержимое маркируется как stdout. В противном
случае токенизация выполняется на stdin.
Примеры¶
Пример переписчика сценария, преобразующего float литералы в десятичные объекты:
from tokenize import tokenize, untokenize, NUMBER, STRING, NAME, OP
from io import BytesIO
def decistmt(s):
"""Заменитm десятичные дроби на числа с плавающей точкой в строке операторов.
>>> 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
Выходные данные вычислений с десятичной запятой должны быть одинаковыми для всех
платформ.
>>> 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 ''
Пример токенизации файла программно, считывание строки юникода вместо
байтов с помощью 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)