pyparsing之后该做什么?
我有一个很大的语法规则,是用pyparsing这个工具开发的,作为一个大型纯Python应用的一部分。现在我已经把性能调优的办法都用尽了,感觉再继续下去收益越来越小,所以我开始考虑其他的选择。是的,我觉得我已经掌握了大部分的技巧,并且对我的语法和应用进行了详细的性能分析。
接下来该怎么办呢?
我希望能找到一个解析器,它能提供和我现在用的pyparsing一样的可读性和易用性(我使用了pyparsing的很多高级功能,比如解析动作,用来开始处理正在解析的输入),但性能要提升10倍。
我很喜欢我的语法是纯Python写的这一点。
我所有的基本模块都是正则表达式,所以能重复使用它们会很不错。
我知道我不可能什么都要,所以我愿意放弃一些现在拥有的功能,以换取所需的10倍性能。
那我接下来该怎么做呢?
5 个回答
可以考虑使用生成的C/C++解析器,比如ANTLR、flex/bison等。如果你能把所有的动作规则都推迟到解析完成之后再执行,那么你可能可以用简单的代码构建一个抽象语法树(AST),然后通过像SWIG这样的工具把它传回你的Python代码中,接着用你现在的动作规则来处理它。另一方面,要想这样做能提高速度,解析的过程必须是最耗时的部分。如果你的动作规则才是主要的开销,那么这样做对你没有任何帮助,除非你也把动作规则写成C代码(但你可能还是得这么做,以避免Python和C代码之间的兼容性问题)。
如果你真的想要在处理大型语法时提高性能,可以看看 SimpleParse(它本身依赖于一个叫mxTextTools的C语言扩展)。不过,你要知道,这种方法可能会比较复杂,而且需要你对 EBNF 有一定的了解。
这绝对不是更符合Python风格的做法,而且你需要从头开始学习EBNF语法,才能使用SimpleParse。
看起来,pyparsing的开发者们已经预见到了你的问题。从这个链接可以看到:
对于复杂的语法和/或大输入字符串,
pyparsing
的性能可能会比较慢。可以使用psyco
这个包来提高pyparsing
模块的速度,而不需要改变语法或程序逻辑——观察到的性能提升在20%到50%之间。
不过,正如Vangel在下面的评论中提到的,psyco
在2012年3月已经不再更新了。它的继任者是PyPy项目,这个项目从同样的基本思路出发来提升性能:使用JIT本地代码编译器,而不是字节码解释器。如果你能接受切换Python的实现,使用PyPy应该能获得类似或更大的性能提升。
如果你真的追求速度,但又想保持一些可读性和声明式语法,我建议你看看ANTLR。可能不太适合生成Python代码的后端;我对它是否成熟或性能足够高持怀疑态度。我说的是最初的那个:C语言后端。
你可以在解析器的入口点周围包裹一个Python C扩展模块,然后就可以开始使用了。
不过,值得注意的是,在这个转变中你会失去很多:基本上你想在解析器中做的任何Python操作都必须通过C API来完成(这并不太好看)。而且,你需要习惯非常不同的做事方式。ANTLR有它的优点,但它不是基于组合子的,所以你的语法和语言之间的关系就没有pyparsing那么简单流畅。此外,它有自己的一套领域特定语言(DSL),很像lex/yacc,这可能会有一定的学习曲线——但因为它是基于LL的,你可能会发现更容易适应你的需求。