Python3.0 - tokenize y untokenize
-
06-09-2019 - |
Pregunta
Estoy usando algo similar a la siguiente secuencia de comandos simplificada para analizar fragmentos de Python desde un archivo más grande:
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)
A pesar de que el código no es el mismo en python2.X, que utiliza el mismo lenguaje y funciona muy bien. Sin embargo, al ejecutar el código anterior utilizando python3.0, consigo esta salida:
(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
He buscado referencias a este error y sus causas, pero no he podido encontrar ninguna. ¿Qué estoy haciendo mal y cómo puedo corregirlo?
[editar]
partisann 's observación de que añadiendo una nueva línea a la fuente hace que el error desaparezca, empecé a jugar con la lista que fue untokenizing. Parece que el token EOF
provoca un error si no inmediatamente precedida por una nueva línea lo que la eliminación se deshace del error. La siguiente secuencia de comandos se ejecuta sin errores:
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])
Solución
src = 'foo="bar"\n'
You olvidó nueva línea.
Otros consejos
Si limita la entrada a untokenize
a los 2 primeros elementos de las fichas, parece que funciona.
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)