Как использовать tokezine / untokenize?

#python #tokenize

#python #маркировать

Вопрос:

Я пытаюсь перестроить строку кода Python после изменения некоторых элементов с помощью модуля tokenize Python. Простая токенизация / untokenize не перестраивает исходный код, она добавляет дополнительные пробелы в выходных данных.

В untokenize есть ошибка или я что-то упускаю?

 from tokenize import tokenize, untokenize
from io import BytesIO


def retoken(text):
    result = []
    g = tokenize(BytesIO(text.encode('utf-8')).readline)  # tokenize the string
    for toknum, tokval, _, _, _ in g:
        result.append((toknum, tokval))
    return untokenize(result).decode('utf-8')


code = "x.y=12"
print("CODE:", code)
print("RETOKEN:", retoken(code))
  

Выходной сигнал:

 CODE: x.y=12  
RETOKEN: x .y =12
  

Комментарии:

1. Это задокументированное поведение для untokenize : «Гарантия применяется только к типу токена и строке токена, поскольку интервал между токенами (позиции столбцов) может измениться».

2. Похоже, что, основываясь на некоторых легких экспериментах, это untokenize добавляет пробел после токена идентификатора.

3. Обратите внимание, что вы не можете перестроить исходную строку только из токенов, потому что пробел не создаст никаких токенов для untokenize работы. Скорее всего, untokenize вставка пробела в качестве пробела гарантированно не будет частью предыдущего токена и не будет рассматриваться как сам токен другим вызовом tokenize .

4. @chepner не могли бы вы опубликовать свой комментарий в качестве ответа, чтобы я мог его принять? Ссылка на документацию, которую я пропустил, является чистым ответом. Спасибо

Ответ №1:

В документации для untokenize указано, что

[…] интервал между токенами (позиции столбцов) может измениться.

Я подозреваю, что untokenize не проверяет весь список токенов при создании выходной строки. Похоже, что он добавляет пробел после токена идентификатора, поскольку этот символ гарантированно не будет частью ни предыдущего токена идентификатора, ни любого следующего за ним токена, ни самого токена. Это помогает гарантировать, что tokenize(untokenize(tokenize(s))) == tokenize(s) , хотя untokenize(tokenize(s)) может не равняться s .