#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
.