8

我在命令行应用程序中使用 PLY,我将其打包为 Python 鸡蛋,通过pip. 每次我从命令行运行脚本时,都会看到以下消息:

"Generating LALR tables"

此外,parser.out 和 parsetab.py 文件被写入调用脚本的目录。是否有某种方法可以将这些文件与应用程序一起发送,以便它不会每次都重新生成表?

4

5 回答 5

12

采用

yacc.yacc(debug=0, write_tables=0)
于 2013-02-13T22:28:18.127 回答
3

您想通过调用 lex 来使用优化模式

lexer = lex.lex(optimize=1)

.

值得强调(来自同一个链接):

在随后的执行中,将简单地导入 lextab.py 来构建词法分析器。这种方法大大提高了词法分析器的启动时间,并且可以在 Python 的优化模式下工作。

在优化模式下运行时,请务必注意 lex 禁用大多数错误检查。因此,仅当您确定一切正常并且准备好开始发布生产代码时,才真正推荐这样做

由于这是生产代码,这听起来正是您想要的。

.

在研究这个问题时,我发现了一些Yacc 的杂项注释

由于 LALR 表的生成相对昂贵,因此如果可能的话,之前生成的表会被缓存和重用。重新生成表的决定是通过对所有语法规则和优先规则进行 MD5 校验和来确定的。只有在不匹配的情况下才会重新生成表。

深入研究yacc内部的函数yacc.py,我们看到优化忽略了以下代码段中的这种不匹配:

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

wheresignature与存储在parsetab.py(as _lr_signature) 中的校验和进行比较。

于 2012-10-04T16:45:02.630 回答
0

我最终做的是关闭优化。我正在浏览 PLY 3.4 源代码,我在词法分析器代码中发现了这个小块:

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

return lexobj

通过将构建词法分析器和解析器的代码更改为:

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

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

我避免了所有文件的写出。调试器将.out文件写入目录,Python 文件是optimize标志的结果。

虽然这暂时有效,但我不能说我对这种方法完全满意。据推测,有一些方法可以保持优化,同时保持工作目录干净,这将是一个更好的解决方案,可以带来更好的性能。如果其他人有更好的方法,我会更愿意接受。

于 2012-10-07T03:55:44.413 回答
0

这是一个老问题,但是当我尝试使用 yacc 关键字参数将生成的解析器表放置在我的项目中的特定目录中时,我遇到了与 ply 类似的问题outputdir——它会将它们放置在那里,但每次都重新生成它们时间不管。我在 github 上找到了这个补丁,它解决了再生问题,没有明显的不良影响。基本上,它所做的只是修改类read_table上的方法yacc以采用额外的参数 -- outputdir-- 并在重新生成之前搜索那里的目录。为了使其工作,read_table(在方法中yacc)的唯一调用站点也需要修改以传递outputdir关键字参数。

于 2015-04-14T21:13:37.850 回答
-1

显然,在 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):

因此,您只需传递不同的错误日志和调试日志(使用 debug() 等不打印到 stdout/stderr 的方法)。你指定一个固定的输出目录。这就是你需要做的。

更新:我刚刚检查过,这是正确的设置:

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

实际上你需要使用一个已经包含 parsetab.py 的输出目录。这不仅会消除消息,而且您的程序也不会写出 parsetab.py。它只会使用它。

于 2012-10-03T14:25:46.407 回答