> **Источник:** https://python-all.ru/3.4/library/tokenize.html
>
> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.

---

# 32.7. [`tokenize`](https://python-all.ru/3.4/library/tokenize.html#module-tokenize) – Токенизатор исходного кода Python

**Исходный код:** [Lib/tokenize.py](https://python-all.ru/src/3.4/Lib/tokenize.py)

---

Модуль [`tokenize`](https://python-all.ru/3.4/library/tokenize.html#module-tokenize) предоставляет лексический анализатор для исходного кода Python, реализованный на Python. Этот анализатор также возвращает комментарии как токены, что делает его полезным для реализации «pretty-printers», включая раскраску для отображения на экране.

Для упрощения обработки потока токенов все токены [*Операторов*](https://python-all.ru/3.4/reference/lexical_analysis.html#operators) и [*Разделителей*](https://python-all.ru/3.4/reference/lexical_analysis.html#delimiters) возвращаются с использованием общего типа токена [`token.OP`](https://python-all.ru/3.4/library/token.html#token.OP). Точный тип можно определить, проверив свойство `exact_type` в [*именованном кортеже*](https://python-all.ru/3.4/glossary.html#term-named-tuple), возвращаемом из [`tokenize.tokenize()`](https://python-all.ru/3.4/library/tokenize.html#tokenize.tokenize).

## 32.7.1. Токенизация ввода

Основной точкой входа является [*генератор*](https://python-all.ru/3.4/glossary.html#term-generator):

#### `tokenize.tokenize(readline)`

Генератор [`tokenize()`](https://python-all.ru/3.4/library/tokenize.html#module-tokenize) требует один аргумент, *readline*, который должен быть вызываемым объектом, предоставляющим тот же интерфейс, что и метод [`io.IOBase.readline()`](https://python-all.ru/3.4/library/io.html#io.IOBase.readline) файловых объектов. Каждый вызов функции должен возвращать одну строку ввода в виде байтов.

Генератор выдает 5-кортежи со следующими элементами: тип токена; строка токена; 2-кортеж `(srow, scol)` из целых чисел, указывающих строку и столбец начала токена в исходном коде; 2-кортеж `(erow, ecol)` из целых чисел, указывающих строку и столбец конца токена в исходном коде; и строку, в которой был найден токен. Передаваемая строка (последний элемент кортежа) является *логической* строкой; строки продолжения включены. 5-кортеж возвращается как [*именованный кортеж*](https://python-all.ru/3.4/glossary.html#term-named-tuple) с именами полей: `type string start end line`.

Возвращаемый [*именованный кортеж*](https://python-all.ru/3.4/glossary.html#term-named-tuple) имеет дополнительное свойство с именем `exact_type`, которое содержит точный тип оператора для токенов [`token.OP`](https://python-all.ru/3.4/library/token.html#token.OP). Для всех остальных типов токенов `exact_type` равняется полю `type` именованного кортежа.

Изменено в версии 3.1: Добавлена поддержка именованных кортежей.

Изменено в версии 3.3: Добавлена поддержка `exact_type`.

[`tokenize()`](https://python-all.ru/3.4/library/tokenize.html#module-tokenize) определяет кодировку исходного файла, ища BOM UTF-8 или cookie кодировки, в соответствии с [**PEP 263**](https://python-all.ru/3.4/library/tokenize.html).

Все константы из модуля [`token`](https://python-all.ru/3.4/library/token.html#module-token) также экспортируются из [`tokenize`](https://python-all.ru/3.4/library/tokenize.html#module-tokenize), как и три дополнительных значения типа токена:

#### `tokenize.COMMENT`

Значение токена, используемое для обозначения комментария.

#### `tokenize.NL`

Значение токена, используемое для обозначения незавершающего перевода строки. Токен NEWLINE обозначает конец логической строки кода Python; токены NL создаются, когда логическая строка кода продолжается на нескольких физических строках.

#### `tokenize.ENCODING`

Значение токена, указывающее кодировку, используемую для декодирования исходных байтов в текст. Первый токен, возвращаемый [`tokenize()`](https://python-all.ru/3.4/library/tokenize.html#module-tokenize), всегда будет токеном ENCODING.

Предоставляется ещё одна функция для обращения процесса токенизации. Это полезно для создания инструментов, которые токенизируют скрипт, изменяют поток токенов и записывают изменённый скрипт обратно.

#### `tokenize.untokenize(iterable)`

Преобразует токены обратно в исходный код Python. *Итерируемый объект* должен возвращать последовательности как минимум из двух элементов: типа токена и строки токена. Все дополнительные элементы последовательности игнорируются.

Восстановленный скрипт возвращается в виде одной строки. Результат гарантированно токенизируется обратно в соответствии с входными данными, что обеспечивает преобразование без потерь и полную обратимость. Гарантия распространяется только на тип токена и строку токена, поскольку расстояния между токенами (позиции столбцов) могут измениться.

Он возвращает байты, закодированные с использованием токена ENCODING, который является первой последовательностью токенов, выводимой [`tokenize()`](https://python-all.ru/3.4/library/tokenize.html#module-tokenize).

[`tokenize()`](https://python-all.ru/3.4/library/tokenize.html#module-tokenize) необходимо определять кодировку исходных файлов, которые он токенизирует. Функция, которую он для этого использует, доступна:

#### `tokenize.detect_encoding(readline)`

Функция [`detect_encoding()`](https://python-all.ru/3.4/library/tokenize.html#tokenize.detect_encoding) используется для определения кодировки, которая должна использоваться для декодирования исходного файла Python. Она требует один аргумент, readline, так же, как и генератор [`tokenize()`](https://python-all.ru/3.4/library/tokenize.html#module-tokenize).

Она вызовет readline максимум дважды и вернёт используемую кодировку (в виде строки) и список любых строк (не декодированных из байтов), которые она прочитала .

Она определяет кодировку по наличию BOM UTF-8 или cookie кодировки, как указано в [**PEP 263**](https://python-all.ru/3.4/library/tokenize.html). Если присутствуют и BOM, и cookie, но они не согласуются, будет возбуждено SyntaxError. Обратите внимание, что если BOM найден, `'utf-8-sig'` будет возвращена как кодировка.

Если кодировка не указана, то будет возвращена кодировка по умолчанию `'utf-8'`.

Используйте [`open()`](https://python-all.ru/3.4/library/functions.html#open) для открытия исходных файлов Python: он использует [`detect_encoding()`](https://python-all.ru/3.4/library/tokenize.html#tokenize.detect_encoding) для определения кодировки файла.

#### `tokenize.open(filename)`

Открывает файл в режиме только для чтения, используя кодировку, определенную [`detect_encoding()`](https://python-all.ru/3.4/library/tokenize.html#tokenize.detect_encoding).

Новое в версии 3.2.

#### `exception tokenize.TokenError`

Возникает, когда докстринг или выражение, которое может быть разбито на несколько строк, не завершено нигде в файле, например:

```python
"""Beginning of
docstring
```

или:

```python
[1,
 2,
 3
```

Обратите внимание, что незакрытые строки в одинарных кавычках не вызывают ошибку. Они токенизируются как `ERRORTOKEN`, после чего следует токенизация их содержимого.

## 32.7.2. Использование командной строки

Новое в версии 3.3.

Модуль [`tokenize`](https://python-all.ru/3.4/library/tokenize.html#module-tokenize) может быть выполнен как скрипт из командной строки. Это так же просто, как:

```sh
python -m tokenize [-e] [filename.py]
```

Принимаются следующие опции:

#### `-h, --help`

показывает это справочное сообщение и завершает работу

#### `-e, --exact`

отображает имена токенов с использованием точного типа

Если указан `filename.py`, его содержимое токенизируется в stdout. В противном случае токенизация выполняется из stdin.

## 32.7.3. Примеры

Пример переписчика скриптов, преобразующего литералы чисел с плавающей запятой в объекты Decimal :

```python
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')
```

Пример токенизации из командной строки. Скрипт:

```python
def say_hello():
    print("Hello, World!")

say_hello()
```

будет токенизирован в следующий вывод, где первый столбец – это диапазон координат строки/столбца, где найден токен, второй столбец – имя токена, а последний столбец – значение токена (если есть)

```sh
$ 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`:

```sh
$ 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      ''
```
