Python3.0 - токенизировать и токенизировать - PullRequest
2 голосов
/ 01 июня 2009

Я использую что-то похожее на следующий упрощенный скрипт для анализа фрагментов Python из файла большего размера:

import io
import tokenize

src = 'foo="bar"'
src = bytes(src.encode())
src = io.BytesIO(src)

src = list(tokenize.tokenize(src.readline))

for tok in src:
  print(tok)

src = tokenize.untokenize(src)

Хотя в python2.x код не совпадает, он использует ту же идиому и работает просто отлично. Однако, запустив приведенный выше фрагмент с использованием python3.0, я получаю следующий вывод:

(57, 'utf-8', (0, 0), (0, 0), '')
(1, 'foo', (1, 0), (1, 3), 'foo="bar"')
(53, '=', (1, 3), (1, 4), 'foo="bar"')
(3, '"bar"', (1, 4), (1, 9), 'foo="bar"')
(0, '', (2, 0), (2, 0), '')

Traceback (most recent call last):
  File "q.py", line 13, in <module>
    src = tokenize.untokenize(src)
  File "/usr/local/lib/python3.0/tokenize.py", line 236, in untokenize
    out = ut.untokenize(iterable)
  File "/usr/local/lib/python3.0/tokenize.py", line 165, in untokenize
    self.add_whitespace(start)
  File "/usr/local/lib/python3.0/tokenize.py", line 151, in add_whitespace
    assert row <= self.prev_row
AssertionError

Я искал ссылки на эту ошибку и ее причины, но не смог ее найти. Что я делаю не так и как я могу это исправить?

[править]

После того, как partisann заметил, что добавление новой строки к источнику приводит к исчезновению ошибки, я начал возиться со списком, который не писал. Кажется, что токен EOF вызывает ошибку, если ему не предшествует символ новой строки, поэтому его удаление избавляет от ошибки. Следующий скрипт выполняется без ошибок:

import io
import tokenize

src = 'foo="bar"'
src = bytes(src.encode())
src = io.BytesIO(src)

src = list(tokenize.tokenize(src.readline))

for tok in src:
  print(tok)

src = tokenize.untokenize(src[:-1])

Ответы [ 2 ]

3 голосов
/ 01 июня 2009

src = 'foo="bar"\n'
Вы забыли перевод строки.
0 голосов
/ 01 июня 2009

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

import io
import tokenize

src = 'foo="bar"'
src = bytes(src.encode())
src = io.BytesIO(src)

src = list(tokenize.tokenize(src.readline))

for tok in src:
  print(tok)

src = [t[:2] for t in src]
src = tokenize.untokenize(src)
...