2012-09-28 79 views
6

Estoy usando PLY en una aplicación de línea de comandos que incluyo como un huevo de Python para instalar a través del pip. Cada vez que ejecutar mi script desde la línea de comandos, aparece el mensaje siguiente:Cómo evitar la regeneración de tablas en PLY

"Generating LALR tables" 

Además, los archivos parser.out y parsetab.py se escriben en el directorio desde el que se invoca el guión. ¿Hay alguna forma de enviar estos archivos con la aplicación para que no vuelva a generar las tablas todas las veces?

+0

No sé si es posible hacer esto con 'ply'. Puede cambiar el nombre de archivo o directorio para usar, o elegir siempre regenerar las tablas (lo que puede no ser una opción, dependiendo del tamaño de su gramática). Pero para enviar la tabla de analizador generada ... no sé. :/ – elias

Respuesta

0

Lo que finalmente terminé haciendo fue desactivar la optimización. Yo estaba pasando por la fuente PLY 3.4 y me encontré con esta pequeña pepita en el código léxico:

# If in optimize mode, we write the lextab 
if lextab and optimize: 
    lexobj.writetab(lextab,outputdir) 

return lexobj 

Al cambiar el código que construye el léxico y el analizador para:

self.lexer = lex.lex(module=self, optimize=False, debug=False, **kwargs)

y

self.lexer = lex.lex(module=self, optimize=False, debug=False, **kwargs)

Evité todas las entregas de archivos. El depurador escribe .out archivos en el directorio y los archivos de Python son el resultado del indicador optimize.

Si bien esto funciona por el momento, no puedo decir que estoy totalmente satisfecho con este enfoque. Presumiblemente, tener alguna forma de mantener la optimización y, al mismo tiempo, mantener limpio el directorio de trabajo sería una solución superior que daría como resultado un mejor rendimiento. Si alguien más tiene una mejor metodología, estoy más que abierto a ella.

-1

Al parecer, hay argumentos a favor de esto en ply.yacc:

def yacc(method='LALR', debug=yaccdebug, module=None, tabmodule=tab_module, start=None, 
    check_recursion=1, optimize=0, write_tables=1, debugfile=debug_file,outputdir='', 
    debuglog=None, errorlog = None, picklefile=None): 

lo tanto, sólo pasa un registro de errores y DebugLog diferente (con una depuración(), etc. métodos que se imprime en stdout/stderr) Y especifica un dir_informe fijo. Y eso es todo lo que necesitas hacer.

ACTUALIZACIÓN: Acabo de comprobar y este es el ajuste correcto:

yacc.yacc(
    debug=False,       # do not create parser.out 
    outputdir=r"c:\temp\aaa" # instruct to place parsetab here 
) 

En realidad es necesario utilizar un outputdir que ya contiene parsetab.py. Esto eliminará no solo el mensaje, sino que su programa no escribirá parsetab.py. Simplemente lo usará.

+1

El OP no solicita simplemente no mostrar el mensaje, pero no regenerar los archivos de las tablas del analizador temporal todo el tiempo. – elias

+0

Supongo que cuando utiliza un directorio fijo y ya coloca los archivos allí, no se regenerarán. Pero intentaré y le dejaré saber los resultados. – nagylzs

+0

'debug = False' suprime el mensaje de error, pero no suprime la generación del archivo. Cuando lo uso junto con la ubicación de implementación (donde ya existen los archivos), todavía intenta sobrescribirlos. – Michael

2

que desea utilizar optimized mode, llamando lex:

lexer = lex.lex(optimize=1) 

.

Vale la pena enfatizar (from the same link):

, en posteriores ejecuciones, lextab.py simplemente se importará para construir el analizador léxico. Este enfoque mejora sustancialmente el tiempo de inicio del Lexer y funciona en el modo optimizado de Python.

Cuando se ejecuta en modo optimizado, es importante tener en cuenta que Lex desactiva la mayoría de las comprobaciones de errores. Por lo tanto, esto es realmente solo recomendado si está seguro de que todo está funcionando correctamente y está listo para comenzar a liberar el código de producción.

Dado que este es el código de producción, esto suena exactamente como usted lo desea.

.

Al analizar esta cuestión, me encontré con el miscellaneous Yacc notes:

Desde la generación de las tablas LALR es relativamente caro, tablas generadas previamente se almacenan en caché y volver a utilizar si es posible. La decisión de regenerar las tablas se determina tomando una suma de comprobación MD5 de todas las reglas gramaticales y de precedencia. Solo en el caso de una discrepancia, las tablas se regeneran.

Y mirando más profundamente en la función yacc dentro yacc.py, vemos que optimizan la ignora este desajuste en el siguiente fragmento:

if optimize or (read_signature == signature): 
    try: 
     lr.bind_callables(pinfo.pdict) 
     parser = LRParser(lr,pinfo.error_func) 
     parse = parser.parse 
     return parser 

donde signature se compara con la suma de comprobación almacenada en parsetab.py (como _lr_signature).

+0

¿Hay algo que deba hacer además de establecer optimize = 1 en el analizador y el lexer? Cuando lo hago, aún se regeneran los archivos y aún se imprime el mensaje. – Michael

11

uso

yacc.yacc(debug=0, write_tables=0) 
+0

Nota: realmente debería usar 'debug = False, write_tables = False'. El '0' simplemente funciona, pero es más explícito usar' True'/'False' y la documentación también usa' bool' y no enteros. – Bakuriu

0

Ésta es una vieja pregunta, pero me encontré con un problema similar con capas cuando traté de utilizar el argumento de palabra clave outputdir yacc para colocar las tablas del analizador generados en directorios específicos dentro de mi proyecto - - Los colocaría allí, pero los volvería a generar cada vez independientemente. Encontré this parche en github que resolvió el problema de regeneración sin efectos negativos notables. Básicamente, todo lo que hace es modificar el método read_table en la clase yacc para tomar un parámetro adicional - el outputdir - y busca en el directorio allí antes de volver a generar. Para que funcione, el único sitio de llamada al read_table (en el método yacc) también debe modificarse para pasar el argumento de palabra clave outputdir.

Cuestiones relacionadas