Python tokenize中的bug?

1 投票
1 回答
525 浏览
提问于 2025-04-16 10:14

为什么这段

if 1 \
and 0:
    pass

最简单的代码在进行分词和还原词时会出错呢?

import tokenize
import cStringIO

def tok_untok(src):
    f = cStringIO.StringIO(src)
    return tokenize.untokenize(tokenize.generate_tokens(f.readline))

src='''if 1 \\
and 0:
    pass
'''
print tok_untok(src)

它抛出了一个错误:

AssertionError:
File "/mnt/home/anushri/untitled-1.py", line 13, in <module>
  print tok_untok(src)
File "/mnt/home/anushri/untitled-1.py", line 6, in tok_untok
  tokenize.untokenize(tokenize.generate_tokens(f.readline))
File "/usr/lib/python2.6/tokenize.py", line 262, in untokenize
  return ut.untokenize(iterable)
File "/usr/lib/python2.6/tokenize.py", line 198, in untokenize
  self.add_whitespace(start)
File "/usr/lib/python2.6/tokenize.py", line 187, in add_whitespace
  assert row <= self.prev_row

有没有什么办法可以解决这个问题,而不需要修改要进行分词的源代码(看起来是\引起的)

另一个失败的例子是如果最后没有换行,比如src='if 1:pass'也会出现同样的错误

解决办法:

但似乎用另一种方式进行还原词是可行的

def tok_untok(src):
    f = cStringIO.StringIO(src)
    tokens = [ t[:2] for t in tokenize.generate_tokens(f.readline)]
    return tokenize.untokenize(tokens)

也就是说,不要把整个词元元组传回去,只传递前两个元素 t[:2]

尽管Python文档说额外的参数会被忽略

将词元转换回Python源代码。可迭代对象必须返回至少包含两个元素的序列,分别是词元类型和词元字符串。任何额外的序列元素都会被忽略。

1 个回答

3

是的,这个问题是一个已知的 bug,而且大家希望能有一个比现在这个更好的修复方法。现在正是为改进 Python 贡献力量的好时机;)

撰写回答